【过个好年一定要看】Linux Crontab“宁死不执行”的神坑
一、背景二、问题排查2.1 怀疑 crond 未启动2.2 检查系统日志2.3 细查crontab条目三、分析总结
一、背景
年底业务复盘安全检查,突然发现正常运行了几个月的发布工具备份全部没了,当下就是心头一惊。还好这期间发布管理机正常运行,不然当真要凉。
二、问题排查
大家先看看这三条crontab,觉得有什么问题吗?初看确实没什么问题,原因很简单:
因为crontab -e
编辑完保存时会自动检查语法
,如果语法问题会报错且无法保存。
而更让我无法怀疑crontab
的另一个理由是这几条crontab是跑了小半年都正常运行,只是在最近几个月突然出现这个问题。
2.1 怀疑 crond 未启动
简单的ps
后,确认crontab
正常运行
# ps aux | grep cron
root 68830 0.0 0.0 116884 1284 ? Ss 16:29 0:00 crond
root 74801 0.0 0.0 103324 900 pts/14 S+ 16:59 0:00 grep --color=auto cron当时第一个
2.2 检查系统日志
tail /var/log/messages
检查系统日志,发现:
crontab
正常运行而独独第二条命令压根没执行
2.3 细查crontab条目
至此,问题简单定位到是第二条crontab
写法的问题,但是仍不知道问题所在。
此时,我也没有什么思路,考虑到我使用的pyenv虚拟环境
管理系统python
环境,且ansible-playbook
是系统之外的工具,因此所有的疑点聚焦在ansible-playbook
命令上,因此就有了,图一中的第三条contab
12 15 * * * cd /data/sa/AutomaticTool;source ~/.bash_profile; source ~/.bashrc; ansible-playbook test.yml &> /tmp/ansibleping.log
test.yml非常简单的去ping下自己,目的在于检查
ansible-playbook
命令是否能正常运行
- hosts: localhost
remote_user: root
tasks:
- name: ping test
ping:
编辑好crontab
,设定离现在最近的时间点,重启crond
服务使crontab
最快的速度生效
重启crond
# service crond restart
Stopping crond: [ OK ]
Starting crond: [ OK ]
追踪日志确认
crond
是否正常执行
# cat /tmp/ansibleping.log
PLAY [localhost] ***************************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [ping test] ***************************************************************
ok: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0
发现竟然正常执行了。。。这个时候我是有点懵的。仔细想了下,问题肯定还是在这附近,只是我的验证案例不够
**精确**
,因此有了图一中的第一条crontab
19 15 * * * cd /data/sa/AutomaticTool; source ~/.bash_profile; source ~/.bashrc; ansible-playbook AutomaticToolBackup.yml &> /data/sa/Backup/AutomaticToolBackup.log-2018181818.log
这条crontab和图一第三条crontab的区别在于更加精确
追踪日志
发现日志也是正常写入。。。不过这里基本上也能确认下来,是
date +%Y%m%d-%H%M%S
这段代码的问题。。而:
这条
crontab
没有改动过,有过近半年的正常运行crontab
没有语法报错,且正常保存
看起来是哪里的知识有漏嘴,犯了基本的错。 google下来后果然发现问题了,被坑的人还不少。。
%
在crontab
里代表有“结束命令行”、“换行”、“重定向”的作用,如果要使用%
需要使用转义符转义
三、分析总结
crontab
在Linux系统里经常因为死循环、环境变量、秒级执行等问题被冠名”不靠谱”,资深运维也一再告诫不要使用crontab
,但在实际场景里,crontab的功能确实有很多不可替代的应用场景,如何避免类似神坑且快速解决问题故障只能上线前多测试了,当用Linux系统的crontab
了。哈哈
根据经验大家可以从如下解决分析解决问题:
1、检查 crontab 服务是否正常
一般通过查看日志来确认,/var/log/cron
和/var/log/messages
,如果里面没有发现执行记录,需要确认crond
服务是否正常,重启服务:service crond restart
2、检查脚本的执行权限
一般来说,在 crontab
中建议使用 sh
或 bash
来执行 shell
脚本,避免因脚本文件的执行权限丢失导致任务失败。当然,最直接检查就是人工直接复制crontab -l
里面的命令行测试结果。
3、检查脚本需要用到的变量
环境变量简直是crontab
出故障的第一杀手,和上文一样,通常来说从 crontab
里面执行的脚本和人工执行的环境变量是不一样的,所以对于一些系统变量,建议写绝对路径,或使用which
动态获取,比如 sudo_bin=$(which sudo)
就能拿到 sudo
在当前系统的绝对路径了。
4、查看日志
其实,最直接最有效的就是查看执行日志了,结合crontab
执行记录,以及 crontab
执行出错后的系统邮件,一般都能彻底找到失败的原因了!
5、google
google不必多说 ,基本上遇到的所有问题都能告诉你如何解决。