我已经在 crontab 上栽了很多次跟头了,我决定写个总结。
常用的命令
crontab -l # 显示计划任务脚本
crontab -e # 编辑计划任务
计划任务的格式
时间格式
* # 每个最小单元
/ # 时间步长,每隔多长时间执行 */10
- # 区间,如 4-9
, # 散列,如 4,9,10
几个例子
crontab 最小支持的时间单位是 1 分钟,不支持每个多少秒执行一次
# 每分钟执行
* * * * * cmd
# 每小时的15,45分钟执行
15,45 * * * * cmd
# 每个周一到周五,早上9点到下午6点之间,每隔15分钟喝一次水
*/15 9,18 * * 1-5 喝水
每个 X 秒执行
crontab 的默认最小执行周期是 1 分钟,如果想每隔多少秒执行一次,就需要一些特殊的手段。
每隔 5 秒
* * * * * for i in {1..12}; do /bin/cmd -arg1 ; sleep 5; done
每隔 15 秒
* * * * * /bin/cmd -arg1
* * * * * sleep 15; /bin/cmd -arg1
* * * * * sleep 30; /bin/cmd -arg1
* * * * * sleep 45; /bin/cmd -arg1
为什么 crontab 指定的脚本没有执行?
有以下可能原因
- 没有权限执行某个命令
- 某个命令不在环境变量中,无法找到对应命令
首先你必须测试一下,你的脚本不使用 crontab 能否正常执行。
大部分 crontab 执行不成功,都是因为环境变量的问题。
下面写个例子:
#!/bin/bash
now=`date`
msg=`opensips -V`
echo "$now $msg \n\n" >> /root/test.log
cd /root
sh test.sh
ctrontab -e 将 test.sh 加入 crontab 中
* * * * * sh /root/test.sh
centos crontab 的执行日志在/var/log/cron 中,可以查看执行日志。
我的机器是树莓派,没有这个文件,但是我是把执行输出到/root/test.log 中的,可以查看这个文件
可以看到虽然输入了事件,但是并没有输出 opensips 的版本
Mon 1 Jul 13:04:01 BST 2019
Mon 1 Jul 13:05:01 BST 2019
将$PATH 也加入输出,发现Mon 1 Jul 13:10:01 BST 2019 /usr/bin:/bin,而 opensips 这个命令是位于/usr/local/sbin 下,所以无法找到执行文件,当然无法执行
#!/bin/bash
now=`date`
msg=`opensips -V`
echo "$now $PATH $msg \n\n" >> /root/test.log
那还不好办吗?
在当前工作目录执行 echo $PATH, 然后在脚本里设置一个环境变量就能搞定
#!/bin/bash
PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
now=`date`
msg=`opensips -V`
echo "$now $PATH $msg \n\n" >> /root/test.log
也可以使用 journalctl -t CROND
查看 crond 的日志
检查 crontab 是否运行
systemctl status crond
systemctl restart crond
在 alpine 中执行 crontab
alpine 中没有 systemctl, 需要启动 crond 的守护进程,否则程序定时任务是不会执行的
#!/bin/sh
# start cron
/usr/sbin/crond -f -l 8