crontab 定时任务不执行?九个高频坑
答案:九成是环境问题——cron 用最小 PATH、不加载 .bashrc,命令要写绝对路径;脚本加执行权限、把输出重定向到文件看报错,再查 cron 服务与系统日志。内联命令注意 % 要转义。
一、标准排查顺序
systemctl status cron # Debian/Ubuntu;RHEL 是 crond
crontab -l # 确认任务真的保存了、是期望的用户
grep CRON /var/log/syslog # Debian;RHEL 看 /var/log/cron
# 任务里务必重定向输出,否则报错邮件默认看不到把任务先改成可观测形式:
*/2 * * * * /opt/job.sh >> /tmp/job.log 2>&1# 脚本开头打点,确认是否触发
#!/bin/bash
date '+%F %T start' >> /tmp/job.log二、最高频:PATH 与环境变量
交互终端能跑、cron 失败,几乎都是环境差异:
# crontab 里明确 PATH,或任务脚本用绝对路径
PATH=/usr/local/bin:/usr/bin:/bin
*/5 * * * * /usr/bin/python3 /opt/app.py >> /tmp/app.log 2>&1java/python/node写全路径(which java查),不要依赖JAVA_HOME/nvm/虚拟环境的登录初始化。- 需要登录环境就在脚本内
source /etc/profile、source ~/.bashrc或激活虚拟环境,而不是假定 cron 帮你做。 - 工作目录也可能不是家目录:脚本内
cd /opt/project || exit 1,或全程绝对路径,相对路径是另一大坑。
三、权限、换行、百分号
- 执行权限:
chmod +x /opt/job.sh;或直接用解释器调/bin/bash /opt/job.sh(不依赖可执行位)。 - 百分号转义:crontab 命令行里未转义
%被当作换行:
# 错误:+%F 里的 % 会断行
0 2 * * * tar czf /backup/app-$(date +%F).tar.gz /data
# 正确:转义,或干脆放进脚本
0 2 * * * tar czf /backup/app-$(date +\%F).tar.gz /data- 结尾换行:crontab 最后一行必须以换行结束,否则最后一条可能不执行。
- 编码:保存为 UTF-8/ASCII、LF 换行(Windows 编辑过的脚本常见 CRLF,bash 报
bad interpreter,用dos2unix修)。
四、时间字段与系统级任务
分 时 日 月 周
*/5 * * * * # 每 5 分钟
0 2 * * 0 # 每周日 02:00- 周和日同时受限是"或"不是"与",容易算错。
- 服务器时区用
timedatectl/date确认,容器默认 UTC 最常见。 /etc/cron.hourly|daily下由run-parts调用,文件名不能含点号(backup.sh会被跳过,要叫backup-sh或backup);先run-parts --test /etc/cron.daily看哪些会被选中。- 用户任务
crontab -e(按用户隔离),系统任务/etc/crontab、/etc/cron.d/*(多一个"用户"字段)。
五、看不到输出
cron 默认把 stdout/stderr 通过本地 mail 发给对应用户(往往没配 MTA 就丢了)。务必显式 >> log 2>&1;调试期可临时 >> /tmp/cron.log 2>&1。应用自己写日志的(见查看日志),也直接 tail 应用日志判断。
FAQ
Q: crontab 为什么不执行? A: 多为最小环境(PATH 短、无 .bashrc),命令用绝对路径/显式 source;其次脚本无执行权限、相对路径、时间写错。
Q: 怎么确认执行了? A: 任务重定向 >> log 2>&1,看 /var/log/syslog(或 cron) 的 CRON 行,脚本开头 date 打点。
Q: 终端能跑 cron 失败? A: 交互登录的环境变量/PATH 在 cron 不存在,写绝对路径并在脚本内 source 环境。
Q: 百分号坑? A: crontab 中裸 % 被当换行,date +%F 要写 +\%F,复杂逻辑放脚本里。
Q: cron 服务和系统任务? A: systemctl status cron/crond 确认在跑;/etc/cron.* 走 run-parts,文件名不能带点号,用 run-parts --test 校验。
一句话总结:crontab 不执行先怀疑环境——绝对路径、显式 PATH/环境变量、chmod +x、避免相对路径;输出一律 >> log 2>&1 并查 syslog/cron;内联 % 转义、末行留换行、CRLF 用 dos2unix,系统级任务文件名别带点号。