cron 与你的 shell 不是一回事
很多定时任务「手动能跑、定时就失败」,根本原因是 cron 环境与登录 shell 不同:cron 只有极简的 PATH(通常不含 /usr/local/bin 等),不加载 .bashrc/.profile,因此 alias、自定义环境变量、某些应用的 PATH 都不存在。写脚本时第一件事是显式设置 PATH 与必要的变量,不要依赖交互式环境。
基本语法
cron 表达式由五到七个字段组成(分 时 日 月 周 [秒]),字段间用空格分隔。常用写法:每天凌晨 2 点执行用 0 2 * * *;工作日每小时执行用 0 * * * 1-5;每 5 分钟执行用 */5 * * * *。日期字段与星期字段同时指定时,多数实现取「或」的关系,容易写错,能只用一个就只用一个。
命令写法注意事项
- 用绝对路径调用可执行文件与脚本
- 输出必须显式重定向,否则 cron 会尝试邮寄给本地用户
- 典型写法:command >> /var/log/job.log 2>&1
- 脚本内 cd 到工作目录,避免相对路径失败
- 避免多条 cron 行执行同一脚本造成并发冲突
常见失败原因
| 现象 | 原因 |
|---|---|
| 手动成功,定时失败 | PATH 或环境变量缺失 |
| 完全没执行 | crond 服务未运行、语法错误被 cron 忽略、用户无权限 |
| 执行了但没效果 | 工作目录不对、相对路径失效、权限不足 |
| 重复执行 | 多台机器或多个配置文件里写了同一条 |
排查步骤
- 确认服务状态:systemctl status crond(或 cron)
- 用 run-parts 或手动以 cron 用户身份执行同一命令,复现环境
- 检查 /var/log/cron 或 journalctl -u crond 看任务是否被调度
- 检查脚本日志与返回值
- 确认脚本可执行位与文件属主正确
防重入与可靠性
任务耗时可能超过调度间隔,导致上一次还没结束下一次又启动。做法是在脚本开头检测锁文件是否存在,存在则直接退出;或用 flock 包裹执行。对于备份这类关键任务,还应记录开始结束时间、校验产物是否完整、失败时主动告警——一个静默失败的备份任务比没有备份更危险。
管理建议
把所有定时任务集中在一个版本可控的脚本仓库里,注释清楚用途与负责人,定期盘点无用任务。每季度跑一次清单核对,能避免「已离职同事写的神秘脚本还在跑」这类隐患。