服务器上的定时任务突然不执行了,日志里却一片安静,用 crontab -l 也能看到配置,可任务就是没跑。这是服务器运维里最常见的坑之一。这篇文章教你从 cron 服务本身、执行环境、文件权限、时区、资源占用几个角度逐层定位,并给出可以直接套用的验证命令。读完你就能独立完成 crontab 不执行的排查,减少反复重启服务器的折腾。下面所有示例都基于常见的 Linux 发行版,并假设你的系统使用 systemd 作为初始化服务。

先确认 cron 守护进程真的在运行
很多人在排查时第一反应是检查 crontab -l 的输出,但这只能证明定时任务已经被写入,并不能说明调度服务本身在跑。在 systemd 环境下,cron 以服务形式存在,一旦服务意外停止或从未启用,所有任务都会静默失效。先执行下面两条命令确认:
systemctl status cron
systemctl is-enabled cron
如果看到服务状态不是 active (running),就把它启动并设为开机自启:
sudo systemctl enable --now cron
需要提醒的是,不同发行版的 cron 服务名可能不同,有的叫 cron,有的叫 crond。你可以用 systemctl list-units | grep -i cron 先找到正确名字,再对号入座。这一步虽简单,却常被跳过,而它恰恰能解释为什么任务完全没有任何执行痕迹。

检查执行环境与 PATH,脚本里的命令找不到
cron 执行脚本时,并不会继承你在终端登录后手动 export 的那些环境变量,它只提供一个非常精简的 PATH。如果你的脚本里直接用命令名(比如 php、mysqldump、ffmpeg),在 cron 里很可能因为找不到命令而静默失败,退出码非零但日志被丢弃。这是定时任务不执行或”执行了却没效果”最常见的原因之一。
最稳妥的做法是脚本内使用绝对路径,或者在 crontab 顶部显式声明 PATH。下面是一个同时处理了两者的示例:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
* * * * * /usr/bin/php /var/www/backup.php >> /var/log/backup.log 2>&1
把标准输出和错误都重定向到日志文件,是排查定时任务的黄金习惯。脚本里的命令是否都能被找到,可以用 which 和 type 在脚本里提前确认,也可以先手动以最小环境跑一次:env -i /bin/sh /path/to/script.sh,这样能模拟 cron 的贫瘠环境,快速暴露缺命令的问题。这类环境变量相关的坑,也常出现在网站性能优化的场景里,值得一并留意。

核对脚本权限与所属用户
cron 会以 crontab 所属用户的身份执行任务,并受到文件系统权限的约束。脚本若缺少可执行权限,或者属主与调度用户不一致,都可能被跳过。常见的表现是:任务在终端里手动跑完全正常,交给 cron 就毫无动静。先检查脚本本身的属性:
ls -l /var/www/backup.php
确认脚本至少对执行用户具有读和执行权限。如果脚本是从别处复制来的,属主可能变成了 root 或其他用户,导致定时任务所属用户无法访问。此时可以修正属主与权限,例如:
sudo chown www-data:www-data /var/www/backup.php
sudo chmod 750 /var/www/backup.php
同时检查脚本要写入的日志、临时目录是否允许该用户写入。权限不足时,脚本可能刚开始就报错退出,但因为输出被丢弃,你在日志里什么都看不到。

排除时区错位造成的”不执行”假象
还有一种隐蔽情况:任务其实执行了,只是时间对不上,看起来像”没执行”。cron 默认使用系统时区来匹配你填写的时间字段。如果服务器时区是 UTC,而你以为写的是北京时间,那么原定 02:00 的任务会跑到 10:00 才触发。先用这两条命令确认服务器当前时间和时区:
date
timedatectl
若时区不符合预期,可以设置为东八区:
sudo timedatectl set-timezone Asia/Shanghai
对于依赖精确时间点的任务,建议在脚本开头把目标时区一并确认,避免夏令时切换或时区变更导致调度错乱。把”时间对不对”和”任务跑没跑”分开验证,排查会高效很多。
关注资源占用与脚本卡死
即使 cron 服务正常、脚本权限无误,任务也可能因为资源不足或上一次运行未结束而被跳过。许多 cron 调度器默认不允许同一任务并发执行,如果脚本里有个循环或网络请求迟迟不结束,下一次触发就会被忽略。观察进程与资源:
ps aux | grep -i backup
free -h
df -h
如果发现任务进程长期滞留,优先给脚本加上超时控制,例如用 timeout 300 /usr/bin/php /var/www/backup.php 限制单次运行时长。磁盘写满或内存耗尽同样会导致任务静默失败,这类问题通常在 dmesg 或系统日志里留有线索。
WordPress 站点的 WP-Cron 与真实 crontab
跑 WordPress 站点时,还会遇到一个特殊的坑:很多站点依赖 WP-Cron 通过页面访问触发任务,而不是真正的系统 crontab。如果你的站点流量低,WP-Cron 可能长时间不被触发,导致备份、更新等计划任务”名义上存在、实际从不执行”。想了解 WordPress 侧定时任务的正确配置方式,可以参考站内 WordPress 分类下的相关教程,也可以对照服务器分类里更系统的运维文章。稳妥的做法是在系统 crontab 里显式调用 WordPress 的调度入口,用真实定时任务替代依赖访客的 WP-Cron,让站点在低流量时也能稳定完成任务。
总结与下一步建议
crontab 不执行的排查,本质是沿着”调度服务 → 执行环境 → 文件权限 → 时间 → 资源”这条链逐层排除。建议你按顺序先确认 cron 服务状态,再检查脚本 PATH 与绝对路径,随后核对权限、时区和资源占用,最后针对 WordPress 场景单独处理 WP-Cron 与系统 crontab 的关系。每改一处配置,就把输出重定向到日志再观察一轮,用证据而不是猜测推动排查。
如果你的服务器经常因为负载、磁盘或时区问题让定时任务反复出状况,可以考虑把关键业务迁移到资源更充裕、运维更省心的独立服务器或 VPS(虚拟专用服务器)上,让 cron 这类后台任务跑得更稳定。Hostease 提供的独立服务器与 VPS 方案都支持按需扩展资源,配合面板管理定时任务会更直观,你可以参考Hostease VPS 主机页面了解具体规格。排查脚本本身没有捷径,但把日志、路径、权限这三个基础项做好,大部分问题都能在十分钟内定位。