Mac 中的定时任务
写了一堆爬虫丢服务器上跑,很显然隔一段时间这个爬虫就会废掉。IP 被封是理所当然的。
所以决定放到本地。第一时间 想到的是crontab
, 按照Linux 配置一通,发现任务无法执行。
Mac OS launchd
不用想, 定时器不会被执行的,crontab 已经被 Mac OS废弃了,替代品就是 launchd
launchd 配置目录
用来存放 定时器任务配置文件的 有5个目录 ,官方
- /System/Library/LaunchDaemons 不用登陆也要运行,Apple 提供的系统守护进程
- /System/Library/LaunchAgents Apple提供的代理,适用于每个用户的所有用户
- /Library/LaunchDaemons 不用登陆也要运行,第三方系统守护进程
- /Library/LaunchAgents 需要root登录并且配置文件归root所有
- ~/Library/LaunchAgents 需要非root登录,并且配置文件归非root所有
进到对应作业的目录
当然是 不登陆也要运行的,一开机,不输入密码也要搞起来。
cd /Library/LaunchDaemons
创建plist配置文件
在对应的目录创建配置文件
vi com.vix.cron.plist
内容如下:
<?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.vix.cron</string>
<key>ProgramArguments</key>
<array>
<string>/Users/chuchur/crontab-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/test.err</string>
<key>StandardOutPath</key>
<string>/tmp/test.out</string>
</dict>
</plist>
大概意思就是没60秒执行一次 /Users/chuchur/crontab-test.sh
加载配置文件
使用 launchctl
加载配置文件
launchctl load com.vix.cron.plist
# or
# launchctl load /xxx/xxx/com.alvin.crontabtest.plist
不需要定时器了可以卸载
launchctl unload /xxx/xxx/com.alvin.crontabtest.plist
查看有多少作业在执行
sudo launchctl list | grep 'cron'
但是看这个只是简单的任务逻辑,复杂的怎么办,时分秒日月周 几个小时,几天执行一次。当然他除了StartInterval
还有StartCalendarInterval
<?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.vix.cron</string>
<key>ProgramArguments</key>
<array>
<string>/Users/chuchur/crontab-test.sh</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Day</key>
<integer>11</integer>
<key>Hour</key>
<integer>0</integer>
<key>Minute</key>
<integer>0</integer>
<key>Month</key>
<integer>7</integer>
<key>Weekday</key>
<integer>0</integer>
</dict>
</dict>
</plist>
Mac 只是说废弃了crontab,又没说不再支持了,我就是要用crontab 怎么办?
折腾如下:
配置crontab
借鉴下 Linux 定时任务 配置方法
1)确保crontab 在mac上是运行的
# 定时任务统统由 launchctl 来管理的,看看 cron 任务有没有在里面
sudo launchctl list | grep cron
# 有记录。查看一下启动项的配置
locate com.vix.cron
# 创建一个database
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.locate.plist
# 查看 /etc/crontab 是否存在
ls -alF /etc/crontab
# 创建该文件(如果不存在)
sudo touch /etc/crontab
2)验证crontab是否可以执行
编写定时任务脚本
crontab -e
写入定时任务
0 */1 * * * spider todo
每隔一个小时运行一次。查看任务:
crontab -l
在mac里 ,crontab 配置文件在这个目录 /usr/lib/cron/tabs/
cat /usr/lib/cron/tabs/[user name]
看到的是和 crontab -l
看到的一样,可见配置没有问题的。
3)mac开启crontab的权限
- 系统偏好设置 -> 安全性与隐私 -> 选择 隐私 -> 左侧菜单找到 [完全磁盘访问权限]
- 找到 cron 程序所在目录:
$ whereis cron
# cron: /usr/sbin/cron
$ open /usr/sbin
- 在打开的文件夹内找到 cron
- 把这个文件直接拖动到 系统偏好设置 右侧应用列表框内。勾选上。
收工。
脚本无法运行的解决
脚本无法运行的可以尝试以下:
1)修改 crontab -e ,如 :
* * * * * whoami >> /Users/[your name]/test.txt
改成
* * * * * /usr/bin/whoami >> /Users/[your name]/test.txt
也就是命令要写全路径。
2)修改脚本 头部第二行加上如下代码:
#!/usr/bin/env bash
source /etc/profile #加上这一行
常用命令
* crontab -u user:用来设定某个用户的crontab服务;
* crontab file:file是命令文件的名字,表示将file做为crontab的任务列表文件并载入crontab。如果在命令行中没有指定这个文件,crontab命令将接受标准输入(键盘)上键入的命令,并将它们载入crontab。
* crontab -e:编辑某个用户的crontab文件内容。不指定用户,则编辑当前用户的crontab文件。
* crontab -l:显示某个用户的crontab文件内容,不指定用户,则显示当前用户的crontab文件内容。
* crontab -r:从/var/spool/cron目录中删除某个用户的crontab文件,不指定用户,则默认删除当前用户的crontab文件。
* crontab -i:在删除用户的crontab文件时给确认提示。
语法格式
minute hour day month week command
.---------------------------------- minute (0 - 59) 表示分钟
| .------------------------------- hour (0 - 23) 表示小时
| | .---------------------------- day of month (1 - 31) 表示日期
| | | .------------------------- month (1 - 12) OR jan,feb,mar,apr ... 表示月份
| | | | .---------------------- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat 表示星期(0 或 7 表示星期天)
| | | | | .------------------- username 以哪个用户来执行
| | | | | | .------ command 要执行的命令,可以是系统命令,也可以是自己编写的脚本文件
| | | | | | |
* * * * * user-name command to be executed
例子
大部分情况应该能覆盖了
实例1:每1分钟执行一次myCommand
* * * * * myCommand
实例2:在上午8点到11点的第3和第15分钟执行
3,15 8-11 * * * myCommand
实例3:每隔两天的上午8点到11点的第3和第15分钟执行
3,15 8-11 */2 * * myCommand
实例4:每周一上午8点到11点的第3和第15分钟执行
3,15 8-11 * * 1 myCommand
实例5:每月1、10、22日的6 : 30重启smb
30 6 1,10,22 * * /etc/init.d/smb restart
实例6:每周六、周日的1 : 10重启smb
10 1 * * 6,0 /etc/init.d/smb restart
实例7:每天18 : 00至23 : 00之间每隔30分钟重启smb
0,30 18-23 * * * /etc/init.d/smb restart
实例8:每星期六的晚上11 : 00 pm重启smb
0 23 * * 6 /etc/init.d/smb restart
实例9:每一小时重启smb
* */1 * * * /etc/init.d/smb restart
实例10:晚上11点到早上7点之间,每隔一小时重启smb
0 23-7 * * * /etc/init.d/smb restart
总结:
* 表示任何时候都匹配
"a,b,c" 表示a或者b或者c执行命令
"a-b" 表示a到b之间执行命令
"*/a" 表示每a分钟(小时等)执行一次
crontab 不能编辑系统级的任务