Mac创建定时任务

Mac 有两种方式可以添加定时任务:

  • crontab 命令
  • launchctl 定时任务

crontab 命令

通过crontab 命令,我们可以在固定的间隔时间执行指定的系统指令或 shell script脚本。时间间隔的单位可以是分钟、小时、日、月、周及以上的任意组合。这个命令非常适合周期性的日志分析或数据备份等工作。
命令格式

  1. crontab [-u user] file
  2. crontab [-u user] [ -e | -l | -r ]


  • -u user:用来设定某个用户的crontab服务;
  • file:file是命令文件的名字,表示将file做为crontab的任务列表文件并载入crontab。如果在命令行中没有指定这个文件,crontab命令将接受标准输入(键盘)上键入的命令,并将它们载入crontab。
  • -e:编辑某个用户的crontab文件内容。如果不指定用户,则表示编辑当前用户的crontab文件。
  • -l:显示某个用户的crontab文件内容,如果不指定用户,则表示显示当前用户的crontab文件内容。
  • -r:从/var/spool/cron目录中删除某个用户的crontab文件,如果不指定用户,则默认删除当前用户的crontab文件。
  • -i:在删除用户的crontab文件时给确认提示。

crontab 文件格式
分 时 日 月 星期 要运行的命令

  • 第1列分钟1~59
  • 第2列小时1~23(0表示子夜)
  • 第3列日1~31
  • 第4列月1~12
  • 第5列星期0~7(0和7表示星期天)
  • 第6列要运行的命令

    备份/恢复 crontab


    可以定时备份 crontab 以防误删操作 ```javascript

备份

crontab -l > $HOME/.mycron

恢复

crontab $HOME/.mycron

  1. <a name="vJJWM"></a>
  2. ### 定时实例
  3. ```javascript
  4. # 每1分钟执行一次myCommand
  5. * * * * * myCommand
  6. # 每小时的第3和第15分钟执行
  7. 3,15 * * * * myCommand
  8. # 在上午8点到11点的第3和第15分钟执行
  9. 3,15 8-11 * * * myCommand
  10. # 每隔两天的上午8点到11点的第3和第15分钟执行
  11. 3,15 8-11 */2 * * myCommand
  12. # 每周一上午8点到11点的第3和第15分钟执行
  13. 3,15 8-11 * * 1 myCommand
  14. # 晚上11点到早上7点之间,每隔一小时重启smb
  15. * 23-7/1 * * * /etc/init.d/smb restart

注意清理系统用户的邮件日志


每条任务调度执行完毕,系统都会将任务输出信息通过电子邮件的形式发送给当前系统用户,这样日积月累,日志信息会非常大,可能会影响系统的正常运行,因此,将每条任务进行重定向处理非常重要。 例如,可以在crontab文件中设置如下形式,忽略日志输出:
0 */3 * * * /usr/local/apache2/apachectl restart >/dev/null 2>&1

launchctl 定时任务


下面将手把手教你在mac上创建定时任务。(任务目标:每天晚上十点定时执行/Users/demo/helloworld.py的python程序)

1. 创建run.sh脚本


进入 helloworld.py程序所在目录
cd /User/demo
创建run.sh脚本
vi run.sh
添加执行helloworld.py的命令

:wq保存退出

注意,脚本要改成可执行的权限
chmod 777 run.sh

2. 编写plist文件


launchctl 将根据plist文件的信息来启动任务。
plist脚本一般存放在以下目录:

/Library/LaunchDaemons —>只要系统启动了,哪怕用户不登陆系统也会被执行

/Library/LaunchAgents —>当用户登陆系统后才会被执行

更多的plist存放目录:

  1. ~/Library/LaunchAgents :由用户自己定义的任务项
  2. /Library/LaunchAgents :由管理员为用户定义的任务项
  3. /Library/LaunchDaemons :由管理员定义的守护进程任务项
  4. /System/Library/LaunchAgents :由Mac OS X为用户定义的任务项
  5. /System/Library/LaunchDaemons :由Mac OS X定义的守护进程任务项

进入~/Library/LaunchAgents,创建一个plist文件com.demo.plist

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3. <plist version="1.0">
  4. <dict>
  5. <!-- Label唯一的标识 -->
  6. <key>Label</key>
  7. <string>com.demo.plist</string>
  8. <!-- 指定要运行的脚本 -->
  9. <key>ProgramArguments</key>
  10. <array>
  11. <string>/Users/demo/run.sh</string>
  12. </array>
  13. <!-- 指定要运行的时间 -->
  14. <key>StartCalendarInterval</key>
  15. <dict>
  16. <key>Minute</key>
  17. <integer>00</integer>
  18. <key>Hour</key>
  19. <integer>22</integer>
  20. </dict>
  21. <!-- 标准输出文件 -->
  22. <key>StandardOutPath</key>
  23. <string>/Users/demo/run.log</string>
  24. <!-- 标准错误输出文件,错误日志 -->
  25. <key>StandardErrorPath</key>
  26. <string>/Users/demo/run.err</string>
  27. </dict>
  28. </plist>

launchctl 通过配置文件指定执行周期和任务,不同于 crontab,launchctl 的最小时间间隔是 1s。

plist 文件存放路径为/Library/LaunchAgents或/Library/LaunchDaemons,前者仅当用户登陆后才被执行,后者只要系统启动就会被执行。

支持两种方式配置执行时间:

StartInterval: 指定脚本每间隔多长时间(单位:秒)执行一次;

StartCalendarInterval: 可以指定脚本在多少分钟、小时、天、星期几、月时间上执行,类似如crontab的中的设置,包含下面的 key:

  1. Minute <integer>
  2. The minute on which this job will be run.
  3. Hour <integer>
  4. The hour on which this job will be run.
  5. Day <integer>
  6. The day on which this job will be run.
  7. Weekday <integer>
  8. The weekday on which this job will be run (0 and 7 are Sunday).
  9. Month <integer>
  10. The month on which this job will be run.

3. 加载命令


launchctl load -w com.demo.plist
这样任务就加载成功了。

  1. # 加载任务, -w选项会将plist文件中无效的key覆盖掉,建议加上
  2. $ launchctl load -w com.demo.plist
  3. # 删除任务
  4. $ launchctl unload -w com.demo.plist
  5. # 查看任务列表, 使用 grep '任务部分名字' 过滤
  6. $ launchctl list | grep 'com.demo'
  7. # 开始任务
  8. $ launchctl start com.demo.plist
  9. # 结束任务
  10. $ launchctl stop com.demo.plist

plist 文件的字段说明

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3. <plist version="1.0">
  4. <dict>
  5. <!-- 名称,要全局唯一 -->
  6. <key>Label</key>
  7. <string>com.uniflor.notifier</string>
  8. <!-- 要运行的程序, 如果省略这个选项,会把ProgramArguments的第一个
  9. 元素作为要运行的程序 -->
  10. <key>Program</key>
  11. <string>/Users/uniflor/script.sh</string>
  12. <!-- 命令, 第一个为命令,其它为参数-->
  13. <key>ProgramArguments</key>
  14. <array>
  15. <string>/Users/uniflor/script.sh</string>
  16. </array>
  17. <!-- 运行时间 -->
  18. <key>StartCalendarInterval</key>
  19. <dict>
  20. <key>Minute</key>
  21. <integer>30</integer>
  22. <key>Hour</key>
  23. <integer>9</integer>
  24. <key>Day</key>
  25. <integer>1</integer>
  26. <key>Month</key>
  27. <integer>5</integer>
  28. <!-- 07都指星期天 -->
  29. <key>Weekday</key>
  30. <integer>0</integer>
  31. </dict>
  32. <!-- 运行间隔,与StartCalenderInterval使用其一,单位为秒 -->
  33. <key>StartInterval</key>
  34. <integer>30</integer>
  35. <!-- 标准输入文件 -->
  36. <key>StandardInPath</key>
  37. <string>/Users/uniflor/run-in.log</string>
  38. <!-- 标准输出文件 -->
  39. <key>StandardOutPath</key>
  40. <string>/Users/uniflor/Bin/run-out.log</string>
  41. <!-- 标准错误输出文件 -->
  42. <key>StandardErrorPath</key>
  43. <string>/Users/uniflor/Bin/run-err.log</string>
  44. </dict>
  45. </plist>

配置文件

进入到~/Library/LaunchAgents下建一个plist文件com.test.launchctl.plist,内容如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3. <plist version="1.0">
  4. <dict>
  5. <key>Label</key>
  6. <string>com.test.launchctl.plist</string>
  7. <key>ProgramArguments</key>
  8. <array>
  9. <string>/usr/bin/python</string>
  10. <string>/Workspace/test.py</string>
  11. </array>
  12. <key>StartCalendarInterval</key>
  13. <dict>
  14. <key>Minute</key>
  15. <integer>4</integer>
  16. <key>Hour</key>
  17. <integer>13</integer>
  18. </dict>
  19. <key>KeepAlive</key>
  20. <false/>
  21. <key>RunAtLoad</key>
  22. <true/>
  23. <key>StandardOutPath</key>
  24. <string>/tmp/AutoMakeLog.log</string>
  25. <key>StandardErrorPath</key>
  26. <string>/tmp/AutoMakeLog.err</string>
  27. </dict>
  28. </plist>
  • StartCalendarInterval: 执行周期
  • StandardOutPath: 标准输出路径
  • StandardErrorPath: 错误输出路径
  • RunAtLoad: 加载时执行一次

    管理定时任务

  • 加载任务

    1. cd ~/Library/LaunchAgents
    2. launchctl load com.test.launchctl.plist
  • 卸载任务

launchctl unload com.felink.gitmirror.plist

  • 立即执行一次任务

launchctl start ccom.test.launchctl.plist

  • 停止任务

launchctl stop ccom.test.launchctl.plist
写个简单的applescript。

  1. on callmeican()
  2. set meican_url to "https://meican.com" as string
  3. tell application "Google Chrome"
  4. open location meican_url
  5. activate
  6. end tell
  7. end callmeican
  8. say "不要这么拼了,预订美餐时间到了"
  9. display dialog "不要这么拼了,预订美餐时间到了(截至时间16:30)!" buttons {"好的", "我不定了"} default button 1
  10. if the button returned of the result is "好的" then
  11. -- action for 1st button goes here
  12. callmeican()
  13. end if

脚本的作用大概是MAC会通过弹窗和语音提醒我该订餐了,如果选择定,就自动用浏览器打开订餐的页面。这个脚本每天在四点执行。

1、使用crontab设置定时任务

  1. crontab -e 或者sudo crontab -e
  2. 00 16 * * * osascript /Users/hanlingzhi/project/applescript/meican.scpt


输入完成后,保存退出。系统自动建立新cron,提示如下:crontab: installing new crontab。设置非常简单。

2、使用苹果的Schedule jobs using launchd设置定时任务。需要写一个plist文件,描述任务的动作、间隔的时间、日志输出等参数。

我创建一个plist文件com.hanlingzhi.cron.meican.plist,大概内容如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3. <plist version="1.0">
  4. <dict>
  5. <!-- 名称,要全局唯一 -->
  6. <key>Label</key>
  7. <string>com.hanlingzhi.cron.meican</string>
  8. <!-- 命令, 第一个为命令,其它为参数-->
  9. <key>ProgramArguments</key>
  10. <array>
  11. <string>osascript</string>
  12. <string>/Users/hanlingzhi/project/applescript/meican.scpt</string>
  13. </array>
  14. <!-- 运行时间 -->
  15. <key>StartCalendarInterval</key>
  16. <dict>
  17. <key>Minute</key>
  18. <integer>0</integer>
  19. <key>Hour</key>
  20. <integer>16</integer>
  21. </dict>
  22. <!-- 标准输入文件 -->
  23. <key>StandardInPath</key>
  24. <string>/Users/hanlingzhi/project/applescript/log/run-in-meican.log</string>
  25. <!-- 标准输出文件 -->
  26. <key>StandardOutPath</key>
  27. <string>/Users/hanlingzhi/project/applescript/log/run-out-meican.log</string>
  28. <!-- 标准错误输出文件 -->
  29. <key>StandardErrorPath</key>
  30. <string>/Users/hanlingzhi/project/applescript/log/run-err-meican.log</string>
  31. </dict>
  32. </plist>


然后将plist文件放在/Users/hanlingzhi/Library/LaunchAgents,你的用户目录下,然后执行launchctl load plist就可以启动了。

plist脚本存放路径为/Library/LaunchDaemons或用户目录/Library/LaunchAgents,其区别是后一个路径的脚本当用户登陆系统后才会被执行,前一个只要系统启动了,哪怕用户不登陆系统也会被执行。

可以通过两种方式来设置脚本的执行时间。一个是使用StartInterval,它指定脚本每间隔多长时间(单位:秒)执行一次;另外一个使用StartCalendarInterval,它可以指定脚本在多少分钟、小时、天、星期几、月时间上执行,类似如crontab的中的设置。

  1. <key>StartInterval</key>
  2. <integer>3600</integer>
  3. 或者
  4. <key>StartCalendarInterval</key>
  5. <dict>
  6. <key>Minute</key>
  7. <integer>30</integer>
  8. <key>Hour</key>
  9. <integer>9</integer>
  10. </dict>

launchctl的命令使用大家看一下帮助文档。

由于操作还是比较复杂,为了帮助快速执行,写了个shell快速拷贝新的plist并完成服务重启