吐槽 crontab
干嘛写这玩意呢。。。因为这玩意坑不少。
作为 linux 的计划任务程序,使用方法大家都很清楚:
1 | crontab -e |
然后会用不知道什么程序打开 cron 的配置文件。对我没用错词汇,就是不知道什么程序,我见过用 vim 的、用 nano 的、用一个不知道叫啥名字但快捷键很像 tmux 的(可能是 emcas?),有的系统第一次用 crontab 的时候会让你选用哪种编辑器,但有的完全不会。。。
然后敲命令进去
1 | * * * * * [command] |
那几个星号:
1 | * * * * * |
另外可以用 */n
这种格式,表示时间刻度内执行 n 次。*
既可以填入单个数字表示某一时间,也可以填入类似 1-9
这种形式,表示时间段。
坑来了:后面的命令,有几个值得注意的地方:
运行时涉及的所有文件和命令需要绝对路径。
比如用于 hostloc 一键签到的 php 脚本:
1
php loc.php
在 crontab 中就得这么写:
1
0 1 * * * /usr/bin/php /root/loc.php >>/var/log/hostloc.log
还有 service 之类的命令,得找到 service 的绝对路径:
1
which service
然后类似这么写:
1
0 1 * * * /usr/sbin/service xxx restart
“命令里面夹命令”,需要用
`
号替换括号;如果命令里面有%
号,需要在前面用\
转义。比如:
1
0 0 1 * * /root/traffic.sh > /root/$(date +%y%m%d).txt&&/root/traffic.sh reset
就需要改成
1
0 0 1 * * /root/traffic.sh > /root/`date "+\%y\%m\%d"`.txt&&/root/traffic.sh reset
如果运行出错,crontab 不会主动报错,你可以查看一下 crontab 的 service 日志(参考cron - Where is my logfile of crontab? - Unix & Linux Stack Exchange):
1
2
3
4journalctl -u cron.service
#或者用下面两个
#journalctl _COMM=cron
#journalctl _COMM=cron --since="date" --until="date"或者查看它本身导出的日志文件(不同的 linux 发行版路径可能不一样,以下这个适用于 debian):
1
cat /var/log/syslog
但这样看到的错误日志其实不够详细。仔细观察的话,出错的日志后面有这么一条:
1
(CRON) info (No MTA installed, discarding output)
意思是 cron 想把错误发到系统内的邮件管理器,但你没装。
那就装一个好了:
1
2apt install postfix
service postfix start后续出错的时候就可以通过
1
cat /var/spool/mail/root
查看错误的详细情况。