分享⼀次Linux任务计划crontab不执⾏的问题排查过程
朋友弄了⼀个⼩项⽬,要我帮忙做下 Linux 系统运维,上线⼀段时间后,发现项⽬偶尔会挂掉导致服务不可⽤。开发朋友⼀时之间也没空去研究项⽬奔溃的根因,只好由我这个运维先写⼀个项⽬进程⾃拉起脚本,通过 Linux 任务计划每分钟检查⼀下进程是否存在来避免项⽬挂了没⼈管的情况。
⾃拉起脚本很简单,随便写⼏⾏就搞定了:
Shell
1 2 3 4 5 6 7 8 9 10#!/bin/bash
processcount=$(pgrep my_app|wc -l)
cd $(cd $(dirname $0) && pwd)
if [[ 0 -eq $processcount ]]
then
echo "[ $(date) ] : my_app is down, start it!" | tee -ai ./checkprocess.log        bash ./start.sh #这⾥是项⽬
的重启脚本
else
echo my_app is OK!
fi
然后丢到 crontab,1 分钟执⾏⼀次:
Shell
1* * * * * bash /data/app_server/checkprocess.sh >/dev/null 2>&1
本以为万事⼤吉了,结果还是坑了,进程再⼀次挂了,什么⿁?
⼀、检查⽇志
根据经验,先看⼀下 crontab 的⽇志:
tail /var/log/messages
没发现相关⽇志,看来不是打印到了这,于是查看了下 crontab 的默认⽇志位置:tail /var/log/cron
Shell
1 2 3 4Mar 25 21:40:01 li733-135 CROND[1959]: (root) CMD (sh /data/app_server/checkprocess.sh >/dev/null 2>&1) Mar 25 21:40:01 li733-135 CROND[1960]: (root) CMD (/usr/lib64/sa/sa1 1 1)
Mar 25 21:40:01 li733-135 CROND[1961]: (root) CMD (/usr/sbin/p.org > /dev/null 2>&1)
Mar 25 21:41:01 li733-135 CROND[2066]: (root) CMD (sh /data/app_server/checkprocess.sh >/dev/null 2>&1)
很明显,任务计划确实在正常执⾏着,看来问题在脚本上了。⼆、检查脚本
①、直接执⾏
检查脚本第⼀步,直接按照 crontab ⾥⾯的命令⾏,执⾏脚本:
Shell
1 2 3 4 5sh /data/app_server/checkprocess.sh
[ Fri Mar 25 21:25:01 CST 2016 ] : my_app is down, start it! sh /data/app_server/checkprocess.sh
my_app is OK!
结果进程正常拉起了!
直接执⾏成功,⽽放到 crontab 就失败,经验告诉我肯定的脚本环境变量有问题了!
②、环境变量
于是在脚本⾥⾯载⼊环境变量:
Shell
1 2 3 4#!/bin/bashlinux没有vim命令
#先载⼊环境变量source /etc/profile #其他代码不变
然后⼿⼯把进程杀死,等待⾃拉起,结果... 还是不⾏!
③、系统邮件
经验告诉我,crontab 执⾏失败,如果没有屏蔽错误的话,会产⽣⼀个系统邮件,位置在 /var/spool/mail/root
所以,我把 crontab ⾥⾯的 2>&1 这个屏蔽错误先取消掉,等待⼏分钟查看邮件。cat /var/spool/mail/root 发现有如下报错:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21From root@free-node-us.localdomain  Fri Mar 25 21:30:02 2016
Return-Path: <root@app_server.localdomain>
X-Original-To: root
Delivered-To: root@app_server.localdomain
Received: by app_server.localdomain (Postfix, from userid 0)
id 78DB5403E2; Fri, 25 Mar 2016 21:19:02 +0800 (CST)
From: root@app_server.localdomain (Cron Daemon)
To: root@app_server.localdomain
Subject: Cron <root@app_server> bash /data/app_server/checkprocess.sh >/dev/null Content-Type: text/plain; charset=UTF-8
Auto-Submitted: auto-generated
X-Cron-Env: <LANG=en_US.UTF-8>
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <HOME=/root>
X-Cron-Env: <PATH=/usr/bin:/bin>
X-Cron-Env: <LOGNAME=root>
X-Cron-Env: <USER=root>
Message-Id: <20160325131902.78DB5403E2@app_server.localdomain>
Date: Fri, 25 Mar 2016 21:19:02 +0800 (CST)
start.sh: line 4: /sbin/sudo: No such file or directory #sudo命令不到!我次奥·~
居然是脚本⾥⾯的 sudo 执⾏失败了,不到这个⽂件。看来单纯的载⼊ profile 不⼀定靠谱啊!
③、修复脚本
知道问题所在,解决就简单了,粗暴点,直接写⼊ sudo 的绝对路径 /usr/bin/sudo
继续测试⾃拉起,结果... 还是不⾏!R 了 G 了!!
三、最终解决
继续查看了下系统邮件,发现如下信息:
1 2 3 4 5 6 7 8 9 10 11 12 13Subject: Cron <root@free-node-us> source /etc/profile;bash /data/app_server/checkprocess.sh >/dev/null Content-Type: text/plain; charset=UTF-8
Auto-Submitted: auto-generated
X-Cron-Env: <LANG=en_US.UTF-8>
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <HOME=/root>
X-Cron-Env: <PATH=/usr/bin:/bin>
X-Cron-Env: <LOGNAME=root>
X-Cron-Env: <USER=root>
Message-Id: <20160325132403.0E8E1403E2@app_server.localdomain>
Date: Fri, 25 Mar 2016 21:24:03 +0800 (CST)
sudo: sorry, you must have a tty to run sudo #原来是这个问题!
很明显,提⽰了 sudo 必须需要 tty 才能执⾏,解决很简单,取消这个限制即可!编辑 /etc/sudoers ,到 Defaults    requiretty, 然后注释掉这⾏:
1 2 3vim /etc/sudoers
#Defaults    requiretty
最后使⽤ :x! 或 :wq! 强制保存即可。
结果观察还是报了相同的错误!原来改完这个 sudo 并不会影响已经运⾏的 crontab,所以需要重启 crontab 服务刷新下设置:
1service crond restart
这下终于可以了!
四、分析总结
Linux 系统⾥⾯计划任务,crontab 没有如期执⾏这是运维⼯作中⽐较常见的⼀种故障了,根据经验,⼤家可以从如下⾓度分析解决:
①、检查 crontab 服务是否正常
这个⼀般通过查看⽇志来检查,也就是前⽂提到的 /var/log/cron 或 /var/log/messages,如果⾥⾯没有发现执⾏记录,那么可以重启下这个服务:service crond restart
②、检查脚本的执⾏权限
⼀般来说,在 crontab 中建议使⽤ sh 或 bash 来执⾏ shell 脚本,避免因脚本⽂件的执⾏权限丢失导致任务失败。当然,最直接检查就是⼈⼯直接复制 crontab -l ⾥⾯的命令⾏测试结果。
③、检查脚本需要⽤到的变量
和上⽂⼀样,通常来说从 crontab ⾥⾯执⾏的脚本和⼈⼯执⾏的环境变量是不⼀样的,所以对于⼀些系统变量,建议写绝对路径,或使⽤ witch 动态获取,⽐如  sudo_bin=$(which sudo) 就能拿到 sudo 在当前系统的绝对路径了。
④、放⼤招:查看⽇志
其实,最直接最有效的就是查看执⾏⽇志了,结合 crontab 执⾏记录,以及 crontab 执⾏出错后的系统邮件,⼀般都能彻底到失败的原因了!当然,要记住在 crontab 中如果屏蔽了错误信息,就不会发邮件了。
这⼜让我想起了如果 crontab 未屏蔽⽇志,可能会导致硬盘 inode 爆满 ==>  ,感兴趣的童鞋也可以⾕歌⼀下 /var/spool/clientmqueue/ 这个关键词了解下。
好了,本⽂分享到此,希望对你有所帮助!
Centos7已经写了要chmod +x /etc/rc.d/rc.local 授权⼀下才会起作⽤
当然有的时候也可能不成功,⽐如:
/etc/rc.d/rc.local ⽂件中的内容格式不正确:
开头少了#!/bin/bash,也是执⾏不成功的,会提⽰你格式不对。
也可能由于是环境变量的问题
可直接在/etc/rc.local⽂件中加⼊:source /etc/profile
或者通过 su -c ⾃动带⼊环境变量
此外还可能是没有启动此项服务:
#systemctl list-units --type=service  #来查看⼀下所有的开启启动项⽬⾥⾯有没有这个rc-local这个服务。
#systemctl  status rc-local.service #来查看⼀下当前是怎么个状态
然后:
#systemctl enable rc-local.service
#systemctl start rc-local.service
#⼿⼯添加下开机启动或者⼿⼯起⼀下看报错信息。
另外:服务的启动⽂件是存放在了:/lib/systemd/system/⽬录下⾯,如果不记得这个服务的全称可以来这个⽬录下⾯看。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。