thinkphp 6 中应通过系统 cron 调用 php think 命令行脚本执行定时任务,需编写继承 think\console\command 的命令类,配置绝对路径、正确工作目录,并避免使用 sleep 循环或第三方 task 插件。

ThinkPHP 6 里怎么跑 Cron 脚本
不能直接在 Web 请求里调用定时逻辑,得靠系统级 cron 触发命令行脚本。ThinkPHP 自带的 think 命令行入口就是干这个的,核心是写好命令类,再让 Linux 的 crontab 定期调它。
- 必须用
php think command:name形式执行,不能用php index.php或浏览器访问 - 命令类要继承
think\console\Command,重写configure()和execute() - 确保
php在crontab环境中可用(推荐写绝对路径,比如/usr/bin/php) - 工作目录要设对——
cron默认在 root 目录下运行,得用cd /path/to/project && php think xxx
写一个可被 cron 调用的 ThinkPHP 命令
比如每天凌晨同步订单状态,建命令类 app\command\SyncOrderStatus,别漏掉命名空间和 Command 父类。
-
configure()里用$this->setName('sync:order-status')定义命令名,后续cron就调这个 -
execute()写业务逻辑,直接用模型、Db、Cache 都没问题,TP 的容器和配置已加载 - 别在
execute()里写exit()或die(),会中断命令行流程;用return 0;表示成功 - 加日志比 echo 更靠谱:
trace('sync start', 'cron');或写到runtime/log/cron/下专用文件
php think sync:order-status
cron 表达式和权限坑点
常见错误不是 TP 写错了,而是 crontab 没跑通:环境变量缺失、PHP 版本不一致、权限不够、路径不对。
-
cron不读用户 shell 的~/.bashrc,PATH 往往只有/usr/bin:/bin,所以 PHP、项目路径都得写绝对路径 - 用
crontab -e编辑时,别用sudo crontab -e切换用户后忘了改项目目录权限(比如 www-data 无法读取 .env) - 测试表达式是否生效:先写
* * * * * cd /var/www/myapp && /usr/bin/php think test:ping >> /tmp/cron.log 2>&1,等一分钟看日志 - 避免秒级任务——
cron最小粒度是 1 分钟,想更细得用 workerman/swoole 配合 Redis 锁做调度
为什么不能用 tp 的 task 组件或 sleep 循环
ThinkPHP 官方没内置常驻任务管理器,所谓 “task” 插件大多是轮询+进程锁模拟,线上极易出问题。
-
while(true) { ... sleep(60); }放在 Web 进程里?请求超时、fpm kill、服务器重启都会中断它 - 第三方 task 包依赖
pcntl扩展,而很多共享主机、Docker 镜像默认不装,且 Windows 完全不支持 - 哪怕本地测试能跑,上线后和 Nginx/Apache 的进程模型冲突,容易产生僵尸进程或内存泄漏
- 真正稳定的方案就一个:系统
cron+ TP 命令行,简单、隔离、可观测、易排查
实际部署时最常卡在 cron 环境和项目环境的 PATH、用户、当前目录三者不一致,宁可多写几行 cd 和绝对路径,也别赌“应该能自动找到”。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











