crontab失败主因是执行环境与终端不一致,需确认crond服务状态、用户权限、绝对路径、显式PATH、输出重定向及日志排查。

crontab 本身不直接执行你的脚本或命令——它只按时间触发,真正能否跑通,取决于环境、权限、路径和日志反馈。绝大多数失败不是语法写错,而是执行上下文和你本地终端不一致。
crontab -e 编辑后不生效?先确认服务状态和用户权限
很多新手以为保存就完事了,其实 crontab -e 只是把内容写进 /var/spool/cron/<username></username>,真正干活的是后台的 crond 进程。
- 运行
service crond status或systemctl status crond,确保状态是active (running) - 非 root 用户执行
crontab -e,任务只会以该用户身份运行;若要 root 权限,必须用sudo crontab -e(注意:这不是crontab -u root -e的等价写法,后者可能因权限策略被拒绝) - 检查
/etc/cron.allow和/etc/cron.deny:如果存在cron.allow,只有其中列出的用户才能用crontab;如果只有cron.deny且为空,所有用户默认可用
脚本在终端能跑,但 crontab 里静默失败?重点查三件事
crontab 使用的是极简环境:没有你的 ~/.bashrc,没有 $PATH,也不加载用户 shell 配置。所以常见“找不到命令”“ImportError”“Permission denied”基本都源于此。
- 绝对路径必须写全:
/usr/bin/python3而不是python3,/home/user/script.sh而不是./script.sh - 显式声明环境变量:在 crontab 条目开头加
PATH=/usr/local/bin:/usr/bin:/bin,或在脚本第一行加#!/usr/bin/env python3并确保脚本有执行权限(chmod +x script.sh) - 重定向输出排查问题:
*/5 * * * * /usr/bin/python3 /home/user/job.py >> /tmp/job.log 2>&1—— 不加这句,错误全丢进邮件队列(多数系统默认关邮件),你根本看不到报错
时间表达式写对了,但执行频率不对?注意分钟/小时字段的取值逻辑
看似简单的时间字段,最容易踩坑的是“每 N 分钟”和“跨小时范围”的组合写法。
-
*/10 * * * *表示“每 10 分钟”,即 0、10、20、30、40、50 分各执行一次;但10/10 * * * *是非法写法(起始值不能大于步长) - 想在每天 9–17 点之间每 30 分钟执行一次?别写
0,30 9-17 * * *—— 这实际只在 9:00、9:30、10:00…17:00 执行,共 17×2=34 次;正确写法是0,30 9-16 * * *,再加一行0 17 * * *,因为9-17在 cron 中表示从 9 到 17(含),但 17:30 不符合“每天 9–17 点之间”的业务语义 - 星期几字段:
0和7都是周日,但部分老系统只认0;建议统一用数字0–6(0=周日),避免混用SUN字符串导致兼容问题
日志在哪看?别只盯 crontab -l
crontab -l 只显示你写了什么,不告诉你有没有执行、执行成没成功。真要定位问题,得查两处日志:
-
/var/log/cron:记录 crond 自身调度行为,比如“CMD (python3 /x/y.py)”、“(root) CMD (…)",能看到是否按时触发,但看不到脚本内部错误 -
/var/log/messages或journalctl -u crond:当 crond 启动失败、权限拒绝、加载配置出错时,这里会有更底层提示 - 最关键的一点:如果你没重定向 stdout/stderr,且系统没配 mail 服务,所有输出(包括 Python 的
print()和 traceback)都会被丢弃——这是最常被忽略的盲区
真正卡住的往往不是“怎么写 cron 表达式”,而是“为什么它看起来没动”。把 PATH、cd、权限、输出重定向 四件事一次性配齐,80% 的问题当场消失。


















