必须用绝对路径调用PHP解释器、cd到项目根目录、显式设置APP_ENV环境变量,三者缺一不可;否则因cron环境缺失PATH、autoload.php路径错误或配置加载异常导致失败。

Linux cron 调用 php think 命令总失败?先锁死三要素
直接写 * * * * * php think task:send 几乎必翻车。根本原因不是命令写错,而是 cron 运行时缺失关键上下文。
- 必须用绝对路径调用 PHP:
/usr/bin/php,不能只写php(cron 不读你的$PATH) - 必须
cd到项目根目录再执行:否则think找不到vendor/autoload.php,报Class not found - 必须显式指定环境变量:
APP_ENV=production,否则配置加载错乱,数据库连接、缓存驱动都可能出问题
正确写法示例:0 2 * * * cd /var/www/myapp && APP_ENV=production /usr/bin/php think cleanup:logs >> /var/log/cleanup.log 2>&1
cron 配置里 think:timer 或 think:run 是什么?别用
ThinkPHP 官方没有 think:timer 这个内置命令,也不存在能长期驻留的 think:run。你看到的这类写法,要么是第三方扩展伪造的,要么是误传。
-
think:timer在 TP6/TP8 中并不存在,运行会直接报Command "timer" is not defined - 所谓“框架内置定时器”本质是行为(Behavior)+ 请求触发,依赖用户访问,
app_end钩子每来一次请求才检查一遍时间戳,漏跑率极高 - 真要秒级精度或高可靠性,必须走系统 cron + CLI 命令,或者上 Workerman/Swoole 常驻进程
自定义命令类写完,为什么 php think 列表里看不到?
常见原因是命令类没被自动发现,或命名空间/路径不匹配。TP6/TP8 默认只扫描 app/command 下的类,且要求命名空间与目录结构严格一致。
立即学习“PHP免费学习笔记(深入)”;
- 类文件必须放在
app/command/(TP8)或application/command/(TP6),不能放错层级 - 命名空间必须是
app\command(TP8)或app\command(TP6),不是app\admin\command或app\common\command - 类名需遵循 PascalCase,且
configure()中setName('xxx:yyy')的值必须唯一,不能和其他命令重复 - 首次添加命令后,建议清空
runtime/cache/目录,避免命令注册缓存未更新
日志空白、任务静默失败?检查这三处输出重定向
很多任务看似没执行,其实是执行了但错误被吞掉,或者日志路径不可写。
-
>> /path/to/log只追加标准输出(stdout),PHPerror_log()、异常堆栈、trigger_error()默认走 stderr,必须加2>&1合并重定向 - 确保日志目录存在且 web 用户(如 www-data)或 cron 所属用户有写权限,
runtime/log不是安全选择——cron 通常以 root 或普通用户运行,和 Web 进程用户不同 - 在命令
execute()开头加error_reporting(E_ALL); ini_set('display_errors', '1');,再配合2>&1,才能捕获致命错误
真正难排查的问题,往往卡在环境变量缺失、工作路径错误、日志权限不足这三点上,而不是业务逻辑本身。



















