这个场景要解决什么
任务到点没动静,排查要分两段:先确认它有没有被触发,再确认触发之后为什么失败。这两段彼此独立,混在一起查会绕圈——很多时候任务根本没被调度,此时讨论脚本内部逻辑就是白费工夫。按下面的顺序走,每一步都能给出一个二选一的结论,八步之内通常能锁定原因。
基本信息
| 适用场景 | 任务表里的任务没有按预期执行,或执行了却没有产出 |
|---|---|
| 方法 | 分层验证:触发链(服务、日志、格式、任务表)→ 执行链(环境、权限、路径、脚本) |
| 输出形式 | 每一步一条可直接复制的命令 |
| 前提 | 知道任务属于哪个用户,以及任务表文件的位置 |
第 1-4 步 触发链
第 1-4 步 触发链
systemctl is-active cron 2>/dev/null || systemctl is-active crond # 1 服务在跑?
sudo grep CRON /var/log/syslog | tail -n 5 # 2 日志见触发?
sudo journalctl -u cron --since '30 min ago' | tail -n 5 # 3 journal 兜底
crontab -l | cat -A | sed -n '1,20p' # 4 有无隐藏字符与语法错第 5-8 步 执行链
第 5-8 步 执行链
sudo ls -l /var/spool/cron/crontabs/root # 5 任务表存在且权限对?
env -i PATH=/usr/bin:/bin /bin/sh -c '/opt/app/job.sh; echo rc=$?' # 6 空环境手动跑
ls -l /opt/app/job.sh # 7 执行位与 shebang
bash -x /opt/app/job.sh 2>&1 | tail -n 30 # 8 带追踪复跑分层排查对照
| 层 | 要回答的问题 | 典型症状 |
|---|---|---|
| 服务层 | cron 守护进程在运行吗 | 所有任务都不执行 |
| 触发层 | 到点有没有被唤起 | 个别任务不动,日志里没有任何记录 |
| 格式层 | 任务表能不能被解析 | 报语法错误,或整张表被忽略 |
| 任务表层 | 文件在不在,属主与权限对不对 | 某个用户的任务全部不执行 |
| 环境层 | PATH、SHELL、变量是否齐备 | 手工能跑,cron 里报命令找不到 |
| 权限层 | 有没有执行位与文件访问权 | 报 Permission denied |
| 逻辑层 | 脚本内部是否真的执行成功 | 有执行记录,但没有预期产出 |
常见根因排序
- 环境与 PATH 差异,占大多数情况
- 权限与执行位问题
- 任务表里的隐藏字符或语法错误
- 依赖的服务、网络或挂载还没就绪
- 脚本没有重定向输出,出错信息被直接丢弃
判断有没有触发只认日志:cron 每执行一条任务都会在系统日志里留下记录。日志里没有对应记录,就说明问题出在触发侧而不是脚本里。
临时加一条每分钟执行的观测任务(例如把 env 导出到文件)能快速看清 cron 的真实环境,但务必用后立即删除,否则它会长期占用资源并污染日志。
快速自检的三条命令
- crontab -l 里搜任务关键词,确认条目还在,并且没有被注释掉
- 用 systemctl list-timers 与 crontab -l 区分这条任务到底归 cron 还是 systemd timer
- 在目标机上执行 date,确认时间与时区正确,时钟漂移会让「到点」变得不确定
把任务的输出统一重定向到文件(>> /var/log/job.log 2>&1),是让下一次排查少走弯路最划算的一次改动。
排查期间临时改成每分钟执行确实方便,但会放大脚本本身的副作用;对会写数据库或发通知的任务,先在测试环境验证逻辑,再回到原计划频率。
日志位置随发行版不同:Debian 系常见 /var/log/syslog 里的 CRON 记录,RHEL 系在 /var/log/cron。只在新系统上找 syslog,很容易误判成「没有日志」。
如果任务写在 /etc/cron.d 或系统级 crontab 里,排查时别忘了它们比用户任务表多一个用户字段;用 crontab -l 看不到这些条目,得直接读文件。
观测动作与风险
| 动作 | 能确认什么 | 风险 |
|---|---|---|
| 导出运行环境 | 调度时的真实变量与路径 | 需立即删除,否则长期占用 |
| 临时改为每分钟 | 触发链路是否通畅 | 脚本副作用被同步放大 |
| 输出重定向到文件 | 失败原因与退出码 | 需控制文件增长 |
| 空环境手工执行 | 是否只是环境差异 | 不代表调度时刻的状态 |
| 查看触发日志 | 任务是否被调度 | 日志位置随发行版不同 |
定位到根因后要把改动固化:把环境变量、绝对路径、输出重定向与失败告警写进任务定义,再按原计划频率恢复执行,并把这次的结论写进任务说明里。否则下次换人排查时,同样的八步还要再走一遍,前面的时间就白花了。