Docker中Supervisor进程显示运行但停止调度任务问题排查
1. Worker配置文件中多余的[supervisord]段
你的worker配置文件(/etc/supervisor/conf.d/*.conf)中包含了重复的[supervisord]配置段:
[supervisord] nodaemon=false
这属于错误配置:Supervisor的主配置文件(/etc/supervisor/supervisord.conf)已定义核心的[supervisord]配置,被include的子配置文件仅需定义[program:*]类的进程相关配置,重复的[supervisord]会引发配置冲突,干扰Supervisor的正常运行逻辑。
修复:删除worker配置文件中的[supervisord]整段内容。
2. Laravel队列命令的队列名格式错误
你的worker启动命令中,队列名被不必要的大括号包裹:
php /var/www/api/artisan queue:work redis --queue={gdf_exports}
大括号会被识别为队列名的一部分,导致Worker实际监听的队列是{gdf_exports}而非预期的gdf_exports。即使初始运行正常,后续投递到正确队列的任务会无法被Worker获取,表现为“任务调度停止”。
修复:移除队列名的大括号,修正命令为:
# gdfexports-worker php /var/www/api/artisan queue:work redis --queue=gdf_exports --tries=1 --timeout=3600 # buildroute-worker php /var/www/api/artisan queue:work redis --queue=build_route --tries=10 --timeout=60
3. Docker启动命令中的&符号问题
你的Docker启动命令使用了后台运行符号&:
supervisord -n -c /etc/supervisor/supervisord.conf &
supervisord -n本身就是让Supervisor以前台模式运行,添加&会将其转入后台,导致Docker容器的PID 1变为启动脚本进程而非Supervisor进程。当启动脚本执行完毕后,PID 1退出,Docker会向容器内所有进程发送终止信号,可能导致Worker进程进入异常挂起状态(进程存在但无法处理任务)。
修复:去掉&符号,让Supervisor作为容器的PID 1进程运行:
supervisord -n -c /etc/supervisor/supervisord.conf
4. 补充:Laravel Worker内存泄漏防护
即使修复上述配置,Laravel队列Worker长期运行可能因内存泄漏导致进程挂起。可通过两种方式优化:
- 在Worker命令中添加内存限制参数(例如限制为128M):
php /var/www/api/artisan queue:work redis --queue=gdf_exports --tries=1 --timeout=3600 --memory=128
- 在Supervisor的
[program:*]段设置定期重启逻辑,配合Laravel的queue:restart命令实现Worker的周期性刷新。
内容的提问来源于stack exchange,提问作者Daniele

