supervisor 下 php think queue:work 进程异常退出主因有三:stderr 输出触发 autorestart、daemon 模式内存溢出遭 oom kill、stopwaitsecs 过短致强制终止;需重定向日志、限制内存、调大 stopwaitsecs 并优化 retry_after。

Supervisor 启动的 php think queue:work 进程突然消失
根本原因不是队列本身出错,而是 Supervisor 默认把标准错误(stderr)当作进程异常信号——只要 queue:work 输出了 warning、notice 或未捕获的异常日志到 stderr,Supervisor 就会判定进程“非正常退出”,触发 stop → start 循环,造成“无故退出”的假象。
实操建议:
- 在 Supervisor 配置中显式关闭
autorestart=unexpected的敏感行为,改用autorestart=true+startretries=0,避免因单次 stderr 输出误判 - 强制将 ThinkPHP 的日志输出重定向到文件,不让它走 stderr:
php think queue:work --daemon --quiet >> /var/log/tp-queue.log 2>&1 - 检查
queue.php配置里的failed驱动是否为database或redis,避免因失败任务表缺失导致 silent fail
ThinkPHP queue:work 在 --daemon 模式下内存持续增长
这是最隐蔽的退出诱因:PHP 进程不重启,但内存涨到系统 OOM killer 触发时,进程会被强制 kill,Supervisor 只看到“退出码 -9”,查不到日志,误以为是代码崩溃。
实操建议:
- 必须启用
--memory=128参数(单位 MB),例如:php think queue:work --daemon --memory=128 --sleep=3 - 不要依赖默认的
--delay=3,高并发下积压任务多,--sleep=3能减少空转,降低内存驻留时间 - 确认项目里没在闭包或事件监听器中长期持有大对象(如 DB 查询结果、Excel 导入缓存),这类泄漏在 daemon 模式下会逐轮累积
Supervisor 配置里 stopwaitsecs 太小导致强制 kill
ThinkPHP 的 queue:work 收到 SIGTERM 后,会等当前任务执行完再退出;如果 stopwaitsecs 设为默认的 10 秒,而某个任务耗时 15 秒,Supervisor 就会发 SIGKILL 强制终止——这不是异常退出,是配置不合理。
实操建议:
- 把
stopwaitsecs设为预估最长任务耗时的 2 倍,比如导出报表任务最多 60 秒,就设stopwaitsecs=120 - 配合使用
stopasgroup=true和killasgroup=true,防止子进程残留 - 在
command行末尾加2>&1,确保所有输出进日志,否则supervisorctl tail看不到真实退出原因
重启后队列消费卡在“waiting for job”不动
常见于 Redis 驱动 + retry_after 设置过短,Supervisor 重启瞬间大量任务被标记为“超时失败”,又立刻被重推回队列,形成竞争和阻塞;或者数据库连接未释放,新进程拿不到可用 PDO 实例。
实操建议:
- 检查
config/queue.php中redis.default.retry_after,生产环境建议 ≥ 3600(1 小时),避免频繁重试干扰 - 在
queue:work启动命令前加php think queue:restart,清空旧的 worker 状态标识 - 确认
database.connections.mysql.pdo没被全局变量意外复用,ThinkPHP 6.1+ 推荐显式关闭长连接:'persistent' => false
真正麻烦的从来不是 Supervisor 配不配得上,而是 PHP 进程自己有没有“守规矩”:别让日志乱打 stderr,别让内存悄悄涨满,别让一个任务拖住整个退出流程。这些点漏掉任意一个,Supervisor 就只能当个背锅侠。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










