MacOS的定时任务 launchd

2021-02-23 11:00:28 Falcon

在linux/unix下,我们通常用crontab来定时执行我们的任务,什么是crontab

crontab 是一个可以用来根据时间、日期、月份、星期的组合来调度对重复任务的执行的守护进程。

不过在Mac上,自从10.4(也就是Tiger)起,crontab已经被deprecated了,因为Apple推出了一款更强大的工具launchd

a unified, open-source service management framework for starting, stopping and managing daemons, applications, processes, and scripts. Written and designed by Dave Zarzycki at Apple, it was introduced with Mac OS X Tiger and is licensed under the Apache License.

它吸收了crontab的优点,且更加灵活,更加强大,它除了可以定时执行某些任务,也可以基于某些事件来触发任务,比如当监听到网络连接,或者当观察某个文件被移到某个文件夹,都可以触发我们指定的任务,甚至当执行的任务crash掉了,launchtl能做到让它重新运行!最大的区别是在系统即将sleep或shutdown的情况下,如果此时schedule的任务刚好要执行,两者对它的处理方式的不同,crontab只是简单的不运行此调度任务,但launchd会注意到此任务被终止了,将会在适当的时机再次重启此任务!

 

launchd有两种形式: launchDaemonslaunchAgents,这两种形式有何区别呢?主要区别在于agent代表的是当前已登录的用户执行的任务,而daemon代表的是root用户或者任何你用UserName这个key(这个key在下文所说的plist文件里指定)指定的用户的任务

任务及其表示形式

好了,现在我们已经知道了launchd的功能了,那么我们该如何为其指定一个任务来让其定时执行呢?实际上launchd的每一个任务(job)都对应了一个plist文件(以xml的格式), 它被launchd视为daemon还是agent就看我们把它放在以下哪个目录下了

 

 

位置

代表谁执行

用户代理(User Agents)

~/Library/LaunchAgents

当前登录的用户

全局代理(Global Agents)

/Library/LaunchAgents

当前登录的用户

全局守护进程(Global Daemons)

/Library/LaunchDaemons

root或者在plist里指定UserName此key对应的用户

系统代理(System Agents)

/System/Library/LaunchAgents

当前登录的用户

系统守护进程(System Daemons)

/System/Library/LaunchDaemons

root或者在plist里指定UserName此key对应的用户

 

从上图可知,我们可以将plist文件放在LaunchAgents或LaunchDaemons目录下,都可以定时执行plist里指定的任务,需要注意的是,我们不应该把第三方的任务放在/System/Library上,这个目录下存放着对于操作系统所需要的极其重要的任务!应该把第三方任务放在/Library的LaunchAgents或LaunchDaemons目录下!

 

plist文件格式

好了,前面既然说了job是用一个plist文件来指定的,那我们来看下这个plist文件的格式是咋样的,来看一个demo

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
   <key>Label</key>
   <string>com.example.hello</string>
   <key>ProgramArguments</key>
   <array>
       <string>/Users/ronaldo/test.sh</string>
   </array>
   <key>Nice</key>
   <integer>1</integer>
   <key>StartInterval</key>
   <integer>60</integer>
   <key>RunAtLoad</key>
   <true/>
   <key>StandardErrorPath</key>
   <string>/tmp/AlTest1.err</string>
   <key>StandardOutPath</key>
   <string>/tmp/AlTest1.out</string>
</dict>
</plist>

我们来一步步解释这些key

  • Label 这个key对于每一个job都是必须且惟一的,是每一个job的惟一标识符
  • ProgramArguments 指定了我们要执行的脚本的路径
  • Nice 指定了此任务执行的优先级,从-20到20,数组越低,代表执行的优先级越高
  • StartInterval 指定了每隔多长时间执行一次ProgramArguments指定的脚本(默认单位是秒)
  • RunAtLoad 指定了当脚本被加载时,ProgramArguments指定的脚本就立即执行,对daemon而言,它意味着机器一启动就马上执行,而对agent而言意味着用户一登录就马上执行
  • StandardErrorPath 指定了标准输出错误的路径,比如如果ProgramArguments指定的脚本执行失败了,就会将错误信息写到此错误日志文件里
  • StandardOutPath 指定了标准输出文件的路径,脚本里的任何echo等输出信息可以在此文件里看到

当然以上选项只是选择了几个选项进行说明而已,实际上还有更多的选项可以设定,比如我们还可以指定脚本在每一天的某一时刻执行等等,请自行查阅相关文档

本文收录于