写好一条 crontab,等到点没触发,先怀疑不是 cron 表达式的问题,是 cron 服务本身。Debian 系和 RHEL 系的服务名和日志路径都不一样,一步步查。
第一步:确认服务在跑
Debian / Ubuntu — 服务名叫 cron:
systemctl status cron
sudo systemctl start cron # 没起就启动
sudo systemctl enable cron # 开机自启
CentOS / Rocky / AlmaLinux — 服务名叫 crond:
systemctl status crond
sudo systemctl start crond
sudo systemctl enable crond
粗暴验证:
ps -ef | grep -E 'cron|crond'
看到常驻进程就没死。
第二步:确认任务被 cron 读到了
用户任务:
crontab -l # 查看
crontab -e # 编辑
系统级任务分散在这几处:
cat /etc/crontab
ls /etc/cron.d/
ls /etc/cron.{hourly,daily,weekly,monthly}/
cron 表达式必须以换行结尾——最后一条任务后没换行,很多 cron 实现会直接忽略这一条。
第三步:看日志
Ubuntu / Debian:
grep CRON /var/log/syslog
或走 journalctl:
journalctl -u cron -f
CentOS / Rocky:
grep CRON /var/log/cron
tail -f /var/log/cron
journalctl -u crond -f
日志里应该能看到每次触发的 (user) CMD (...)。看不到说明 cron 根本没执行这条:检查表达式、用户、文件位置。
第四步:cron 环境是”最小 shell”
crontab 里的命令继承的 PATH 极简,通常只有 /usr/bin:/bin。写 python 会找不到,得写绝对路径:
* * * * * /usr/bin/python3 /home/user/task.py
或者在 crontab 里显式设 PATH:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
* * * * * python3 /home/user/task.py
第五步:脚本挂了但看不到报错
cron 默认把 stdout/stderr 发邮件,服务器上一般没配。把输出重定向到日志:
* * * * * /path/to/task.sh >> /var/log/task.log 2>&1
>> /var/log/task.log 追加、2>&1 把 stderr 合流。看日志就能知道到底哪一步失败。
常见坑速查
| 现象 | 原因 |
|---|---|
| 完全没触发 | cron 服务没起 / 表达式写错 |
| 手动跑脚本 OK,cron 跑挂 | PATH 缺、用户身份不同、cwd 不同 |
| 报”command not found” | 命令写了相对路径,改绝对路径 |
| 任务跑了但看不到结果 | 没重定向输出,看邮件或加 >> 日志 |
| 最后一条任务没跑 | crontab 文件末尾没换行 |
| 系统 crontab 没生效 | 系统级 /etc/crontab 需要用户字段 |
系统 crontab 和用户 crontab 的区别
/etc/crontab 每行必须写明执行用户:
0 3 * * * root /root/backup.sh
crontab -e 编辑的用户 crontab 不需要,因为它已经是”这个用户”的。搞混了就没反应。
一句话总结
cron 任务不跑,按 服务状态 → 任务在不在 → 日志 → PATH → 输出重定向 五步走完。90% 的问题在 PATH 缺失或输出被吞。
