先看crond服务是否运行,几乎所有静默失败都源于此;再检查命令绝对路径、环境变量、时间字段逻辑(日与周为“或”关系)、用户级与系统级配置格式差异及日志重定向。

crontab任务不执行?先看crond服务有没有在跑
几乎所有静默失败都源于crond(或cron)服务没启动。你crontab -e保存成功,不代表任务会运行——它只是把配置写进/var/spool/cron/用户名,真正干活的是后台进程。
- 查状态:
systemctl status cron(Ubuntu/Debian)或systemctl status crond(CentOS/RHEL) - 若显示
inactive (dead),立刻执行:sudo systemctl start cron或sudo systemctl start crond - 加开机自启:
sudo systemctl enable cron(别漏这步,重启后又失效) - 确认进程在跑:
ps aux | grep crond,看到/usr/sbin/crond -n才算真活了
crontab里命令找不到?路径和环境变量是硬伤
你在终端敲php script.php能跑,放进crontab就报command not found,不是PHP没装,是cron默认PATH极窄(通常只含/bin:/usr/bin),也不加载你的~/.bashrc。
- 所有命令必须用绝对路径:
/usr/bin/php、/bin/bash、/usr/local/bin/python3 - 脚本本身也要给执行权限:
chmod +x /path/to/script.sh - 更稳妥做法:在
crontab -e顶部加两行(注意这是用户级crontab的写法):SHELL=/bin/bashPATH=/usr/local/bin:/usr/bin:/bin - 调试时务必重定向日志:
0 2 * * * /usr/bin/php /home/user/task.php >> /tmp/task.log 2>&1
每天凌晨2点执行,为什么每月1号也触发了?
这是crontab最反直觉的坑:day-of-month(第几日)和day-of-week(星期几)是“或”关系,不是“且”。写成0 2 * * 1(每周一2点),但若当天恰好是每月1号,它也会执行。
- 想严格按星期跑?把日期字段留
*:0 2 * * 1 /cmd(✅ 正确) - 想严格按日期跑?把星期字段留
*:0 2 1 * * /cmd(✅ 正确) - 千万别填两个具体值,比如
0 2 1 * 1——这表示“每月1号或每周一”,不是“每月1号的周一” - 星期字段注意:0和7都代表周日,1=周一,6=周六;部分老系统不认
mon,只认数字
/etc/crontab和/etc/cron.d/里的格式为什么多一列?
用户级crontab -e和系统级/etc/crontab或/etc/cron.d/xxx文件格式不同——后者必须显式指定执行用户,前者默认用当前用户。
- 用户级(
crontab -e):分 时 日 月 周 命令(6列,无用户字段) - 系统级(
/etc/crontab或/etc/cron.d/myjob):分 时 日 月 周 用户名 命令(7列,第六列是用户) -
/etc/cron.d/下文件权限必须是644:sudo chmod 644 /etc/cron.d/mytask,否则cron直接忽略 - 不要手改
/var/spool/cron/xxx——用crontab -e编辑,否则可能锁死或语法校验失效
真正卡住人的往往不是语法写错,而是服务没起来、路径没写全、日志没开、或者时间字段逻辑被误解。动手前先systemctl status和tail -f /var/log/syslog | grep cron看一眼,比反复改配置快得多。


















