背景
线上有个脚本一直在凌晨一点的时候跑数据,已经运行了很长一段时间了,结果前两天集成测试反馈有问题,没有数据了,一看数据库,最新的数据也是4月25号生成的,后面的就没了,刚才抽空排查了下,记录下排查过程。
排查过程
脚本问题?
并不是我对自己代码没自信啊!就是因为自信所以首先排查脚本,直接在服务器上 php 命令去执行这个脚本,执行成功,数据也有更新,OK!首先排除脚本问题。
crond服务未启动?
crontab 不是Linux内核的功能,而是依赖一个 crond 服务,这个服务可以启动当然也可以停止。如果停止了就无法执行任何定时任务了。service crond status
可以查看 crond 是否在运行,如果运行了一般会显示 crond (pid 32453) is running...
,如果发现 crond 没有运行,可以使用以下命令启动、关闭、重启、重载:
service crond start //启动服务
service crond stop //关闭服务
service crond restart //重启服务
service crond reload //重新载入配置
如果提示 crond 命令不存在,可能被误删除了,CentOS 下可以通过 yum install vixie-cron、 yum install crontabs
重新安装,现在我的 crond 服务在运行,所以排除服务未启动问题。
权限问题?
脚本没有执行权限?但是我们的脚本都是 root php 脚本路径 这样的方式调用,以root身份运行的,所以权限也没问题。
路径问题?
有的命令在 shell 中执行正常,但是在 crontab 执行却总是失败。所以我在脚本相同目录下新建了一个 test.php,里面就一个 echo 'test',然后新建了一个定时任务 */1 * * * * root php /app/80/api/task/task/antirush/1.0/test.php >> /data/testlog
可以看到,过了一分钟后,data 目录下生成了 testlog 文件,并且里面有一条 test,每隔一分钟就多一条,所以排除路径问题。
时差问题?
因为服务器与客户端时差问题,所以crontab的时间以服务器时间为准。上面问题排查下来,可以直接排除这个时差问题,因为直接将之前测试路径的脚本,改为马上要到来的时间执行,执行成功,所以剔除这个因素。
脚本没有启动?
直接在服务器上访问 /var/log 目录下的 cron 文件,这个文件是 cron 的一个日志文件,里面记录了 crontab 启动的每一个脚本情况,查找脚本关键词 Apr 28 01:00:01 SUNMI-TASK CROND[16978]: (root) CMD (php /app/80/api/task/task/antirush/1.0/index.php)
可以看到,在每天的凌晨一点脚本都被 crontab 启动起来了,所以排除脚本没有启动的原因。
那么问题来了,PHP脚本可以直接执行成功,添加进 crontab,crond 服务也把这个脚本启动起来了,也没有错误日志,就是没有执行起来,哇!真是一波爆炸输出,躺枪。
PHP环境变量?
开始排查脚本执行方式问题,先看root,又去看了下权限,没问题,再看php,这个是在 crontab 上面 PATH 声明的一个环境变量 PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/php/bin
,只能使出杀手锏了,不用相对路径的 php 环境变量了,直接写死 php 的环境变量,将脚本的执行方式改为 0 1 * * * root export PATH=/usr/local/php/bin/:$PATH; php /app/80/api/task/task/antirush/1.0/index.php
,然后时间设为马上要到的时间点,到了时间脚本启动,并执行成功,大功告成!!! 环境变量也会导致脚本执行不成功啊啊啊!!!吐血。。。 是谁改了环境变量,暂且不提,原因也懒得排查了,问题解决就行,记录以自查。
此处评论已关闭