最近经常碰到关于crontab不能执行的,初步总结了有以下几个原因:
第一,脚本的原因:大多数情况下,我们要相信科学,相信计算机,不是有鬼,就是我们的脚本的问题,这种问题导致crontab不能执行的概率占到70%以上。因为程序执行到某一步导致crontab终止执行,我就碰到一次在迁移代码的时候将数据库连错了。导致无法访问而死在那里了。
第二,执行环境问题,当我们碰到第一情况下,一般都可以通过手动执行程序将问题扼杀在摇篮里,一般情况下高手是不应该犯第一种错误的。问题是当我们手动执行成功而crontab不能执行的时候,笔者碰到一次就是执行环境的问题,例如相关路径的设置问题。解决方案:在代码最前面执行 source /home/user/.bash_profile
第三,系统时间不正确。这种问题最好理解,也是比较常见和隐蔽的问题,解决方案:date -s ********
第四,就是我们的脚本是否有可执行权限。必须保证执行脚本的用户有执行改文件的权限。
第五,crontab 守护进程死掉了。这种情况是极少发生的,但也不排除,当我们实在是找不到其他原因的时候可以用。解决方案:重启该进程。
另外,介绍大家一个关于如何查看crontab最修修改时间的方法:
进入目录/var/spool/cron/里面会有N个用户名为文件名的文件,只要建立过crontab的用户在这里都会有以该用户名为文件名的文件,该文件的最后修改时间就是该用户的的crontab的最后修改时间。just do it
有时候前置机会出现死进程等,做了这个自动查杀的脚本,已在sco unix505中测试通过,如想测试,可ps -efl >file ,自行修改file里的进程状态及占用时间,再将脚本的输入源由ps -efl改为从file得到,屏敝 kill -9 $pid, 即可通过tty输出及日志文件观察到正确结果
请大家斧正.谢谢!
(如将此脚本加入crontab,时间自定,即可达到自动查杀超时或僵死的进程)
#!/bin/ksh
#自动查杀超时或僵死的进程的脚本 V050930
#crontab -e
#0,5,10,15,20,25,30,40,45,50,55 * * * * /usr/bin/autokill.sh & #设置为每5分钟检查一次超时进程
#当然简写成这样也成:
*/5 * * * * * /usr/bin/autokill.sh & #设置为每5分钟检查一次超时进程
#为了安全保险起见,此版脚本的清除范围为:由终端启动的,占用CUP时间超过指定时间长度的,非root用户的进程或僵尸进程 ^_^
#检测参数
killlog="/tmp/kill.log" #默认自动清除超时进程或僵死进程的日志
out=60 # 默认的超时时间,以秒为单位,默认为60秒,范围为10秒--36000秒
trap 'rm /tmp/kill.tmp 2>/dev/null' 0 1 2 3 9 15
test $LOGNAME != root && { echo "Sorry ! 本 脚 本 只 能 由 root 操 作 !\n\n" ; exit 1 ; }
test "$out" || { echo "\n 超时时限不能为空\n" ; exit 1 ; }
test "$(echo $out | sed -n '/^[0-9][0-9]*$/p')" || { echo "\n 超时时限只能为整数值\n" ; exit 1 ; }
test $out -ge 10 -a $out -le 36000 || { echo "\n 超时时限范围为10秒--36000秒\n" ; exit 1 ; }
#查找超时或僵尸进程
ps -efl |awk -v outtest=$out '{ outtime=timetest($14) }
$2~/Z/ || ( $3!~/root/ && $13!~/\?/ && outtime=="outtime" ) \
{print $3,$4,$13,$2,$14,$15 }
function timetest(ot)
{
hour=substr(ot,1,2)
min=substr(ot,4,2)
sec=substr(ot,7,8)
if ( hour*3600+min*60+sec > outtest)
return "outtime"
else
return "good"
} ' >/tmp/kill.tmp 2>/dev/null
#保存清除列表
if [ -s /tmp/kill.tmp ]
then
pass=0
error=0
echo "\n清 除 时 间: "$(date +%y/%m/%d-%H:%M:%S)"\n" >> $killlog
awk 'BEGIN{printf("%-8s%-8s%-8s%-7s%-10s%-30s\n"),"用户名","进程号","终端号","状态","占用时间","任务名"}
{ state=statetest($4) ; printf("%-8s%-8s%-8s%-7s%-10s%-30s\n"),$1,$2,$3,state,$5,$6} END{print "\n"}
function statetest(test)
{
if (test=="S") return "睡眠"
if (test=="R") return "运行"
if (test=="Z") return "僵尸"
if (test=="O") return "不存在"
if (test=="B") return "等待"
if (test=="T") return "停止"
if (test=="I") return "中间"
}' /tmp/kill.tmp >> $killlog 2>/dev/null
#清除进程
for pid in $(awk '{print $2}' /tmp/kill.tmp |sort -rn)
do
kill -9 $pid
test $? -eq 0 && \
{ echo "自动清除进程 $pid 成功" | awk '{printf("\n%-14s%-10s%-4s"),$1,$2,$3}' ;
echo "自动清除进程 $pid 成功" | awk '{printf("%-14s%-10s%-4s\n"),$1,$2,$3}' \
>> $killlog 2>/dev/null ; pass=$((pass+1)) ; } || \
{ echo "自动清除进程 $pid 失败" | awk '{printf("\n%-14s%-10s%-4s"),$1,$2,$3}' ;
echo "自动清除进程 $pid 失败" | awk '{printf("%-14s%-10s%-4s\n"),$1,$2,$3}' \
>> $killlog 2>/dev/null ; error=$((error+1)) ; }
done
#保存最终统计结果
test $error -eq 0 && \
{ echo "此次共清除 ${pass} 个进程成功" | awk '{printf("\n\n%-14s%-4s%-10s\n\n"),$1,$2,$3}'
echo "此次共清除 ${pass} 个进程成功" | awk '{printf("\n%-14s%-4s%-10s\n\n"),$1,$2,$3}' \
>> $killlog 2>/dev/null ; } || \
{ echo "此次共清除 ${pass} 个进程成功 ${error} 个进程失败" | \
awk '{printf("\n\n%-14s%-4s%-16s%-10s%-10s\n\n"),$1,$2,$3,$4,$5}' ;
echo "此次共清除 ${pass} 个进程成功 ${error} 个进程失败" | \
awk '{printf("\n\n%-14s%-4s%-16s%-10s%-10s\n\n"),$1,$2,$3,$4,$5}' >> $killlog 2>/dev/null ; }
fi
这个是UNix上写的shell,不知在Linux上可以用不,值得探究。
来源:http://hi.baidu.com/zengyinfei/blog/item/6c2232164d239c4220a4e980.html
http://www.oschina.net/bbs/thread/6561?lp=193
第一,脚本的原因:大多数情况下,我们要相信科学,相信计算机,不是有鬼,就是我们的脚本的问题,这种问题导致crontab不能执行的概率占到70%以上。因为程序执行到某一步导致crontab终止执行,我就碰到一次在迁移代码的时候将数据库连错了。导致无法访问而死在那里了。
第二,执行环境问题,当我们碰到第一情况下,一般都可以通过手动执行程序将问题扼杀在摇篮里,一般情况下高手是不应该犯第一种错误的。问题是当我们手动执行成功而crontab不能执行的时候,笔者碰到一次就是执行环境的问题,例如相关路径的设置问题。解决方案:在代码最前面执行 source /home/user/.bash_profile
第三,系统时间不正确。这种问题最好理解,也是比较常见和隐蔽的问题,解决方案:date -s ********
第四,就是我们的脚本是否有可执行权限。必须保证执行脚本的用户有执行改文件的权限。
第五,crontab 守护进程死掉了。这种情况是极少发生的,但也不排除,当我们实在是找不到其他原因的时候可以用。解决方案:重启该进程。
另外,介绍大家一个关于如何查看crontab最修修改时间的方法:
进入目录/var/spool/cron/里面会有N个用户名为文件名的文件,只要建立过crontab的用户在这里都会有以该用户名为文件名的文件,该文件的最后修改时间就是该用户的的crontab的最后修改时间。just do it
有时候前置机会出现死进程等,做了这个自动查杀的脚本,已在sco unix505中测试通过,如想测试,可ps -efl >file ,自行修改file里的进程状态及占用时间,再将脚本的输入源由ps -efl改为从file得到,屏敝 kill -9 $pid, 即可通过tty输出及日志文件观察到正确结果
请大家斧正.谢谢!
(如将此脚本加入crontab,时间自定,即可达到自动查杀超时或僵死的进程)
#!/bin/ksh
#自动查杀超时或僵死的进程的脚本 V050930
#crontab -e
#0,5,10,15,20,25,30,40,45,50,55 * * * * /usr/bin/autokill.sh & #设置为每5分钟检查一次超时进程
#当然简写成这样也成:
*/5 * * * * * /usr/bin/autokill.sh & #设置为每5分钟检查一次超时进程
#为了安全保险起见,此版脚本的清除范围为:由终端启动的,占用CUP时间超过指定时间长度的,非root用户的进程或僵尸进程 ^_^
#检测参数
killlog="/tmp/kill.log" #默认自动清除超时进程或僵死进程的日志
out=60 # 默认的超时时间,以秒为单位,默认为60秒,范围为10秒--36000秒
trap 'rm /tmp/kill.tmp 2>/dev/null' 0 1 2 3 9 15
test $LOGNAME != root && { echo "Sorry ! 本 脚 本 只 能 由 root 操 作 !\n\n" ; exit 1 ; }
test "$out" || { echo "\n 超时时限不能为空\n" ; exit 1 ; }
test "$(echo $out | sed -n '/^[0-9][0-9]*$/p')" || { echo "\n 超时时限只能为整数值\n" ; exit 1 ; }
test $out -ge 10 -a $out -le 36000 || { echo "\n 超时时限范围为10秒--36000秒\n" ; exit 1 ; }
#查找超时或僵尸进程
ps -efl |awk -v outtest=$out '{ outtime=timetest($14) }
$2~/Z/ || ( $3!~/root/ && $13!~/\?/ && outtime=="outtime" ) \
{print $3,$4,$13,$2,$14,$15 }
function timetest(ot)
{
hour=substr(ot,1,2)
min=substr(ot,4,2)
sec=substr(ot,7,8)
if ( hour*3600+min*60+sec > outtest)
return "outtime"
else
return "good"
} ' >/tmp/kill.tmp 2>/dev/null
#保存清除列表
if [ -s /tmp/kill.tmp ]
then
pass=0
error=0
echo "\n清 除 时 间: "$(date +%y/%m/%d-%H:%M:%S)"\n" >> $killlog
awk 'BEGIN{printf("%-8s%-8s%-8s%-7s%-10s%-30s\n"),"用户名","进程号","终端号","状态","占用时间","任务名"}
{ state=statetest($4) ; printf("%-8s%-8s%-8s%-7s%-10s%-30s\n"),$1,$2,$3,state,$5,$6} END{print "\n"}
function statetest(test)
{
if (test=="S") return "睡眠"
if (test=="R") return "运行"
if (test=="Z") return "僵尸"
if (test=="O") return "不存在"
if (test=="B") return "等待"
if (test=="T") return "停止"
if (test=="I") return "中间"
}' /tmp/kill.tmp >> $killlog 2>/dev/null
#清除进程
for pid in $(awk '{print $2}' /tmp/kill.tmp |sort -rn)
do
kill -9 $pid
test $? -eq 0 && \
{ echo "自动清除进程 $pid 成功" | awk '{printf("\n%-14s%-10s%-4s"),$1,$2,$3}' ;
echo "自动清除进程 $pid 成功" | awk '{printf("%-14s%-10s%-4s\n"),$1,$2,$3}' \
>> $killlog 2>/dev/null ; pass=$((pass+1)) ; } || \
{ echo "自动清除进程 $pid 失败" | awk '{printf("\n%-14s%-10s%-4s"),$1,$2,$3}' ;
echo "自动清除进程 $pid 失败" | awk '{printf("%-14s%-10s%-4s\n"),$1,$2,$3}' \
>> $killlog 2>/dev/null ; error=$((error+1)) ; }
done
#保存最终统计结果
test $error -eq 0 && \
{ echo "此次共清除 ${pass} 个进程成功" | awk '{printf("\n\n%-14s%-4s%-10s\n\n"),$1,$2,$3}'
echo "此次共清除 ${pass} 个进程成功" | awk '{printf("\n%-14s%-4s%-10s\n\n"),$1,$2,$3}' \
>> $killlog 2>/dev/null ; } || \
{ echo "此次共清除 ${pass} 个进程成功 ${error} 个进程失败" | \
awk '{printf("\n\n%-14s%-4s%-16s%-10s%-10s\n\n"),$1,$2,$3,$4,$5}' ;
echo "此次共清除 ${pass} 个进程成功 ${error} 个进程失败" | \
awk '{printf("\n\n%-14s%-4s%-16s%-10s%-10s\n\n"),$1,$2,$3,$4,$5}' >> $killlog 2>/dev/null ; }
fi
这个是UNix上写的shell,不知在Linux上可以用不,值得探究。
来源:http://hi.baidu.com/zengyinfei/blog/item/6c2232164d239c4220a4e980.html
http://www.oschina.net/bbs/thread/6561?lp=193
作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:http://jackxiang.com/post/4172/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!
最后编辑: jackxiang 编辑于2013-8-19 20:49
评论列表
2013-8-19 20:48 | root
好,多谢提醒。
2013-8-19 17:18 | 三江小渡
#0,5,10,15,20,25,30,40,45,50,55 * * * * /usr/bin/autokill.sh & #设置为每5分钟检查一次超时进程这句改成 */5 * * * * /usr/bin/autokill.sh & 吧。。。。
分页: 1/1 1