ondemand模式下进程不释放,本质是未配置pm.process_idle_timeout参数,该参数才是空闲进程回收的唯一开关;宝塔默认不暴露此字段,需手动配置并验证生效,且ondemand模型本身不适用于wordpress等重型php应用。

pm.ondemand 模式下进程不释放,本质不是“不释放”,而是它根本没启动回收逻辑——因为 宝塔默认不配置 pm.process_idle_timeout,而这个参数才是 ondemand 模式下进程空闲后被杀掉的唯一开关。没设它,进程一旦 fork 出来就会一直挂着,直到你手动重启或系统内存压力触发 OOM Killer。
确认是否真在用 ondemand 模式
别只看配置文件写了 pm = ondemand,得验证实际生效值:
- 运行 php-fpm -t && php-fpm -i | grep "pm\|process_idle",检查输出中 pm 的值和 pm.process_idle_timeout 是否有值(非 0)
- 宝塔界面不暴露 pm.process_idle_timeout 字段,即使你改了 www.conf,也要确认它没被宝塔后台覆盖(宝塔会定期重写 pool 配置)
- 查进程启动时间:ps -eo pid,comm,lstart,etime | grep "php-fpm: pool" | head -10,如果一堆进程 etime 超过几小时,基本可断定 idle timeout 没生效
内核资源限制是隐藏推手
即便 pm.process_idle_timeout 设对了,进程也可能卡住不退——常见于系统级资源锁死:
- 文件描述符耗尽:ondemand 进程频繁 fork/exit,容易泄露 fd。用 cat /proc/$(pgrep php-fpm | head -1)/limits | grep "Max open files" 查单进程上限;再用 lsof -p PID | wc -l 看实际占用。若接近上限,需调高 ulimit -n 并在 /etc/security/limits.conf 中固化
- 进程数限制(nproc):PHP 脚本里调 exec() 或 pcntl_fork() 可能触发用户级进程数限额。查 ulimit -u,对比 ps -U www-data | wc -l(假设 PHP-FPM 以 www-data 用户运行)
- 内存 cgroup 限制:Docker 或 systemd 服务若启用了 MemoryMax,会导致进程 exit 后残留 cgroup entry,阻塞后续回收。运行 systemctl show php72-fpm | grep Memory 或检查 /sys/fs/cgroup/memory/ 下对应路径
ondemand 不适合 WordPress 类站点
这不是配置问题,而是模型错配:
- WordPress 单次请求平均加载 50+ PHP 文件,ondemand 每次都要 fork + 加载 + 编译 + OPCache 预热,冷启动常超 300ms,Nginx 容易报 502
- 频繁 fork 带来大量 syscalls,显著抬高 iowait 和 context switch,top 里 %sy 高、%wa 高、cs 值 > 5000 是典型信号
- 真正适合 ondemand 的只有极简场景:纯 JSON API、无数据库、无模板渲染、QPS
快速验证与临时止损
不改配置也能快速判断问题归属:
- 执行 kill -USR2 $(cat /www/server/php/72/var/run/php-fpm.pid)(USR2 是平滑重启信号),观察旧进程是否退出。若不退,说明进程卡在某系统调用中(如 stuck in read()、futex_wait)
- 用 strace -p PID -e trace=close,exit_group,munmap 抓一个长期存活的 idle 进程,看它最后停在哪条系统调用上
- 临时禁用所有插件 + 切默认主题,排除 PHP 层阻塞(比如某插件注册了 shutdown_function 但死循环)
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











