【过个好年一定要看】Linux Crontab“宁死不执行”的神坑

【过个好年一定要看】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

图片

检查系统日志,发现:

  1. crontab正常运行

  2. 而独独第二条命令压根没执行

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

这段代码的问题。。而:

  1. 这条crontab没有改动过,有过近半年的正常运行

  2. 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不必多说 ,基本上遇到的所有问题都能告诉你如何解决。


猜你喜欢

转载自blog.51cto.com/15060546/2651570