crontab 定时任务实战:时间字段、环境变量坑与日志排查
脚本手动跑得好好的,放进 crontab 就是不执行——没有报错、没有输出,像被吞掉了一样。这是 crontab 最经典的翻车现场,九成指向同一个原因(后面讲),但先把 crontab 本身理顺。
这是 Linux 命令系列的一篇,承接 Linux 常见命令与工具地图。cron 是类 Unix 系统的定时任务守护进程,crontab 是管理它的命令——每个用户有一份自己的任务表,按设定的时间自动执行命令。
基本操作:-e、-l,以及要避开的 -r
1 | crontab -e |
被 -r 清空且没有备份的话,任务表找不回来。有个简单的保险:定期 crontab -l > ~/crontab.bak 备份一份。
五个时间字段:分 时 日 月 周
crontab 每行由五个时间字段加一条命令组成,字段顺序固定:
1 | ┌───────── 分钟 (0-59) |
四种常用写法,组合起来能表达绝大多数调度需求:
1 | 0 3 * * * /opt/scripts/backup.sh |
还有一组快捷写法,替代整个五字段:@daily(每天零点)、@hourly、@weekly、@monthly,以及比较特殊的 @reboot(系统启动时执行一次)。
任务不执行的头号原因:cron 的环境变量是极简的
回到开头的问题。cron 执行任务时不加载你的 shell 配置——.bashrc、.zshrc、.profile 统统不读,PATH 通常只有 /usr/bin:/bin 这么两截。你手动跑脚本没问题,是因为交互 shell 里 PATH 齐全;cron 里同一条命令找不到可执行文件,就静默失败了。
两种解法,任选或同时用:
1 | which node |
1 | SHELL=/bin/bash |
输出去哪了:重定向到日志
任务的输出(stdout 和 stderr)默认会尝试通过本地邮件发给用户——绝大多数服务器根本没配邮件服务,输出就这么无声消失了,出错也看不到错误信息。标准做法是自己重定向:
1 | 0 3 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1 |
怀疑任务压根没被触发(而不是执行出错)时,查 cron 自己的日志:
cron 服务的名字随发行版不同:Debian/Ubuntu 系叫 cron,RHEL/CentOS 系叫 crond——先确认自己机器上是哪个,再查它的日志:
1 | systemctl list-units --type=service | grep -E "cron" |
日志里有触发记录但结果不对 → 执行环境问题(八成是上一节的 PATH);连触发记录都没有 → 时间字段写错了。
一个专属坑:% 需要转义
crontab 的命令部分里,% 是特殊字符——未转义的 % 会被当成换行符,它之后的内容全部作为标准输入喂给命令(man 5 crontab 原文如此)。最常见的踩法是在文件名里用 date 生成日期:
1 | 0 3 * * * tar -czf /backup/logs-$(date +\%F).tar.gz -C /var/log . |
实战:每天凌晨增量备份
把前面的点串成一个真实任务——每天凌晨 3 点用 rsync 做增量备份,写日志、防 PATH 坑:
1 | PATH=/usr/local/bin:/usr/bin:/bin |
需求再复杂一点——比如”上一次没跑完就别启动下一次””失败自动重试””依赖网络就绪”——crontab 就力不从心了,那是 systemd timer 的领域,配合 systemctl 那篇 的 unit 文件一起用。日常的定时脚本,crontab 足够。
常用操作速查表
| 操作/写法 | 作用 |
|---|---|
crontab -e |
编辑任务表,保存即生效 |
crontab -l |
查看任务表;crontab -l > 备份文件 定期备份 |
crontab -r |
无确认清空全部任务,慎用,建议永远用 -e 删行 |
| 五字段顺序 | 分 时 日 月 周 |
*/5 / 1-5 / 1,15 |
每隔 5 / 连续范围 / 离散值 |
@daily / @reboot |
每天零点 / 开机执行一次 |
| PATH 坑 | cron 不读 shell 配置,命令写绝对路径或顶部声明 PATH |
>> 日志 2>&1 |
输出重定向进日志,否则静默消失 |
journalctl -u cron |
确认任务有没有被触发 |
\% |
命令里的 % 必须转义,否则命令被截断 |
写到这里
crontab 的语法五分钟就能学会,真正拉开差距的是那几个坑:环境变量极简(绝对路径/声明 PATH)、输出会消失(重定向日志)、% 要转义、-r 别碰。把这四条焊在肌肉记忆里,定时任务”静默失败”的排查时间能从几小时缩到几分钟。








