crontab 是系统级调度器,非 php 功能,其执行失败主因是环境差异:path 缺失、工作目录错误、权限不足、时区不一致及输出未重定向;php 脚本须显式校验 cli 模式、禁用超时、写绝对路径日志;分钟级以上且无依赖/重试/动态调整需求才适用 crontab。

crontab 是 PHP 定时任务的落地核心,不是 PHP 本身的功能,学 PHP 定时任务,本质是学怎么让系统调度器可靠地调起你的 PHP 脚本。
crontab 执行 PHP 脚本失败的常见原因
你写的脚本在终端能跑通,放进 crontab 就静默失败——这不是代码错了,而是环境断了。
-
php命令找不到:crontab 不读你的~/.bashrc,PATH 是精简版。必须用which php查绝对路径,比如/usr/bin/php或/opt/homebrew/bin/php - 工作目录不对:crontab 默认在
/root或/下执行,脚本里写include 'config.php'就直接报错。要么全用绝对路径,要么开头加chdir(__DIR__); - 权限问题:脚本文件本身不需要
+x(php script.php只需可读),但日志目录、缓存目录、数据库连接文件等,必须对 crontab 实际运行用户(如www-data或root)可写 - 时区不一致:服务器时区可能是 UTC,而你期望按北京时间每天 2 点执行。检查
date命令输出,并在 PHP 中用date_default_timezone_set('Asia/Shanghai'); - 输出被丢弃:不重定向 stdout/stderr,错误就消失。务必加上
> /var/log/mytask.log 2>&1
PHP 脚本里必须做的三件事
CLI 环境和 Web 环境完全不同,不能假设任何全局变量或上下文存在。
- 显式判断运行模式:
if (php_sapi_name() !== 'cli') { die('This script can only run in CLI mode.'); } - 禁用超时限制(如果真需要):
set_time_limit(0);,但更推荐把任务拆短,靠crontab频次控制,而不是单次扛 10 分钟 - 记录可追溯日志:别只用
echo,用error_log("Start at " . date('c'), 3, '/var/log/task.log');,日志路径也必须是绝对路径
什么时候该换方案,而不是硬塞 crontab
crontab 最小粒度是 1 分钟,且无法动态调整频率、依赖状态判断或做失败重试。遇到这些情况,说明它已不是最优解:
- 要“每 5 秒查一次 Redis 队列”,这不是定时任务,是长连接消费者,该用
supervisor管理一个常驻 PHP 进程 - 任务执行时间不稳定,怕上一次没结束下一次又触发:得加文件锁(
flock)或数据库行锁,而不是靠删 crontab 规则 - 多个任务之间有依赖(B 必须等 A 成功后才跑):
crontab无法表达依赖关系,该上Laravel Scheduler或自研轻量调度器 - 要支持 Web 界面启停、查看历史、重试、参数配置:说明已超出脚本范畴,该接入专业任务平台(如 Easycron、cron-job.org)或自建管理后台
ps aux | grep php 没进程、tail -f /var/log/syslog | grep CRON 显示“permission denied”时,不知道该查哪一层。环境隔离、路径、权限、输出捕获——这四点没理清,所有“定时逻辑”都只是本地能跑的幻觉。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











