同样的脚本,命令行里跑一次就成功,写进crontab就再没动静。这是定时任务最常见的现象,原因几乎都出在环境上。cron执行的时候不加载用户的bashrc,也不读profile。PATH里只有/usr/bin和/bin。脚本里写的php、python、node,命令行能找到,cron找不到。找不到就是一句command not found,被当成邮件发出去,没人看。工作目录也不一样,cron在用户主目录下执行,脚本里的相对路径全指错地方。输出没有重定向的话,错误全丢了。四条凑一起,看着像没执行。
先确认任务有没有被触发。看cron日志,Debian系在syslog里,RedHat系有单独的cron日志。有执行记录但没效果,是环境问题;连记录都没有,是任务本身没生效。日志默认不一定开着,查不到记录时先用logger手动写一条,确认日志通道是通的。
任务没生效也有几种。crontab改了没保存,或者改在了别的用户下。放在/etc/cron.d里的文件格式多一个字段,第六列是执行用户,少了这一列整行都不执行。文件权限和属主要对,cron会忽略权限过宽的配置。还有一种:文件末尾没有换行,最后一行读不进去。
环境问题的修法很固定。在crontab顶部写PATH,把需要的目录都加进去。脚本里一律用绝对路径。需要别的变量,也在顶部定义,或者让脚本自己export。最省事的做法是让脚本在开头就设好路径和变量,不指望外部环境。
输出必须重定向。每个任务后面跟上重定向,把标准输出和错误都写进日志。没有重定向,cron会把输出当邮件发,本地没配邮件服务就一直失败。有了日志,下次出问题直接翻文件。调试阶段可以临时改成每分钟跑一次,验证完再改回去。改回去之后确认一次任务列表,别留下一个每分钟跑一次的定时炸弹。
还有一个特别容易忘的:百分号。crontab里百分号是换行符,写日期格式化命令会被从那里截断。要么转义,要么把整条命令写进脚本文件。
时区也会骗人。cron用的是系统时区,服务器设成UTC,任务就会在你以为的时间之外跑。部分实现支持单独指定时区的变量。跨时区部署的项目,最好在脚本里自己算时间,别依赖服务器的本地时间。
验证顺序就三步。先看有没有执行记录。再用清空环境的方式手动跑一遍,能不能成功立刻见分晓。清空环境跑能过,说明是环境问题;过不了,问题在脚本本身。
跑通了再观察一天。确认日志有内容、时间对得上。把这条任务的依赖写进注释,下次换机器不会漏。注释里写清楚依赖哪个程序、哪个路径、哪个配置文件,比只写任务用途有用。
A5创业网 版权所有