Docker部署PHP Yii1应用时PHP-FPM报unknown child错误如何解决
报错原因
这个告警并非日志提示的PHP内核bug,属于容器环境下进程托管的常见问题,核心触发逻辑如下:
- PHP-FPM主进程仅能识别自身fork出来的worker子进程,当它收到不属于自己子进程的退出信号时,就会抛出
unknown child类告警 - Docker容器默认无专用init进程的场景下,PHP-FPM以PID 1身份运行,会自动接管容器内所有孤儿进程(父进程先于子进程退出的进程),这些孤儿进程退出时的信号就会触发该报错
- 启动FPM的shell脚本中存在未托管的后台任务、Yii1业务代码中存在请求内创建子进程的逻辑(如异步任务、本地命令调用),也会导致非FPM生成的子进程被挂到FPM进程树下,退出时触发告警
- PHP 7.0之前的老版本存在进程识别逻辑缺陷,也会提高该报错的触发概率
修复方案
- 优先为容器添加专用init进程
启动容器时增加--init参数,由Docker自带的init进程托管孤儿进程,避免PHP-FPM承接不属于自己的子进程。
也可以在Dockerfile中手动安装tini作为init进程,示例配置:# 以alpine镜像为例 RUN apk add --no-cache tini ENTRYPOINT ["/sbin/tini", "--"] # 后续接原有启动命令/脚本配置 - 调整进程管理逻辑
检查启动FPM的shell脚本,确保exec /usr/sbin/php-fpm命令执行前没有带&的后台运行命令,所有常驻后台的任务(如Yii1定时任务、队列消费进程)要么拆分到独立sidecar容器运行,要么使用supervisor等进程管理工具统一托管,不要与FPM共用进程树。 - 优化业务代码
排查Yii1代码中是否存在在Web请求生命周期内调用pcntl_fork、exec创建子进程的逻辑,将这部分逻辑改造为独立控制台命令通过定时任务/队列托管,确实需要在请求内创建子进程的场景,添加posix_setsid()调用让子进程脱离当前会话,避免挂到FPM进程树下。 - 版本适配
若当前使用PHP 7.0及更早版本,可升级至PHP 7.4及以上稳定版本,该版本对FPM进程信号处理逻辑做了优化,可大幅降低该误告警的触发概率。
内容的提问来源于stack exchange,提问作者arjunbnair
相关产品推荐
相关产品推荐

