我们常常会有一些定时任务处理的需求,Linux上大多使用Crontab来实现。
趁机记录下最近新开的一台机上使用Crontab的错误排查。
系统是Ubuntu20.04
前置需求
每天定时运行一次虚拟环境下的Python脚本并留存运行日志保存起来。
最初实现
根据需求,很容易写出下面的规则。
crontab -e
# '>>' 代表追加;2>&1 代表错误输出重定向标准输出,即记录所有输出
15 8 * * * ~/XXX/start.sh >> ~/XXX/run.log 2>&1
start.sh
内容如下
source venv/bin/activate
python push_main.py
信誓旦旦的等待中,到点后却发现run.log
一直都是空的,出现问题了。
错误排查
首先检查命令。
~/XXX/start.sh >> ~/XXX/run.log 2>&1
没问题,正常输出追加log。
查看Crontab状态和执行日志。
# 查看Crontab状态 service cron status ... # 查看Crontab执行日志 grep cron /var/log/syslog ...
发现时间和本地时间不同,并没有执行命令,方便调试,这里我们调成和本地一样的东八区。
timedatectl set-timezone Asia/Shanghai # 重启系统日志和Crontab使其修改生效 systemctl restart rsyslog service crond restart
时区正确后查看执行日志发现找不到
source
命令,且找不到venv/bin/activate
。Crontab所用的
/bin/sh
不包含source
命令,用.
代替运行脚本即可。找不到
venv/bin/activate
,是因为Crontab执行默认是在用户的根目录下,需要提前手动cd,在start.sh
中添加cd ~/XXX/
导出的log中文自动转码
Crontab执行的环境变量和用户不同导致的,在
start.sh
最顶部中添加export LANG=zh_CN.UTF-8
导入即可。
修正后的start.sh
export LANG=zh_CN.UTF-8
cd ~/XXX
. venv/bin/activate
python push_main.py
总结
Crontab执行环境和用户执行环境差的有点多,很零碎的参考,记得快忘的也快。