Linux 定时任务 cron 排错:任务没跑起来先查这 5 处
定时任务没跑起来,第一反应往往是“脚本写错了”。但根据经验,cron 出问题大多不在脚本逻辑本身,而在服务、时间、环境、权限、日志这五个环节。按下面顺序逐一排查,大多数问题十分钟内就能定位。
一、先确认 cron 服务在运行
任务没执行,先看服务本身是不是活着。不同发行版服务名不同:Debian/Ubuntu 叫 cron,RHEL/CentOS 叫 crond。
systemctl status cron || systemctl status crond
ps aux | grep -v grep | grep cron
如果服务是 inactive,启动并设为开机自启:
sudo systemctl enable --now cron # RHEL/CentOS 用 crond
顺带确认系统时间是否正常,时间错了,任务自然“不准时”:
date
timedatectl | head -5
二、检查 crontab 是不是真的写进去了
改完 crontab 不等于任务生效。可能没保存成功,也可能写进了错误的用户。
crontab -l # 查看当前用户的任务列表
sudo crontab -l -u www # 查看指定用户的任务
时间字段顺序是“分 时 日 月 周”,写错一位意思全变。例如 0 2 * * * 是每天凌晨 2 点执行,而 * 2 * * * 是 2 点那一小时每分钟都执行。常见坑还有:
- 最后一行缺少换行符,导致最后一行任务没被识别;
- 日期和星期同时写了限定条件,两者是“或”关系,不是“与”关系;
- 直接改 /etc/crontab 时漏了用户名那一列,系统级 crontab 的格式是“分 时 日 月 周 用户 命令”。
三、环境变量:cron 里的世界和终端不一样
这是最常见的“手动能跑、定时不跑”的原因。cron 以最小环境运行,PATH 只有 /usr/bin:/bin,自定义的 PATH、JAVA_HOME、虚拟环境都读不到。
# 先看 cron 的环境长什么样
* * * * * env > /tmp/cron_env.txt 2>&1
解决办法是脚本里用绝对路径,并在脚本开头显式加载环境:
#!/bin/bash
source /etc/profile
source ~/.bashrc
/usr/local/bin/python3 /opt/scripts/backup.py >> /var/log/backup.log 2>&1
也可以在 crontab 顶部直接定义变量,例如 SHELL=/bin/bash,以及完整的 PATH。
四、权限、可执行位与输出去向
脚本没加执行权限、shebang 写错、输出目录不存在,都会让任务悄悄失败。
ls -l /opt/scripts/backup.py # 确认有 x 权限
chmod +x /opt/scripts/backup.py
head -1 /opt/scripts/backup.py # 第一行应为 #!/bin/bash 之类
另外一定要把输出重定向到日志文件,否则出错信息只会发到系统邮件里,很少有人去翻:
0 3 * * * /opt/scripts/backup.py >> /var/log/backup.log 2>&1
也可以在 crontab 顶部加 MAILTO=ops@example.com,让 cron 把失败输出发到指定邮箱。
五、用日志验证,而不是凭感觉
最后一步是看日志,确认任务到底跑没跑、跑成什么样。
# Debian/Ubuntu
grep CRON /var/log/syslog | tail -20
# RHEL/CentOS
tail -20 /var/log/cron
# systemd 系统通用
journalctl -u cron --since "1 hour ago"
如果日志里根本没有这条任务的记录,说明问题在前四步;如果有记录但脚本报错,就按报错信息修脚本。调试时还可以用一条“探针任务”快速验证 cron 本身是否正常:
* * * * * date "+%Y-%m-%d %H:%M:%S cron is alive" >> /tmp/cron_test.log 2>&1
等一两分钟,看 /tmp/cron_test.log 有没有新行,就知道 cron 服务和调度是否正常,验证完记得删掉这条探针。
总结
cron 排错按“服务—任务表—环境—权限—日志”这个顺序走一遍,能覆盖九成故障。养成两个习惯可以少踩很多坑:脚本永远用绝对路径,输出永远重定向到日志文件。下次任务没跑起来,先查这 5 处,再怀疑脚本本身。
- 点赞
- 收藏
- 关注作者
评论(0)