如何通过Cron定时任务终止运行时长超过1小时的PHP-FPM进程
如何通过Cron定时任务终止运行时长超过1小时的PHP-FPM进程
我完全懂你这种被 runaway PHP-FPM 进程搞崩服务器的头疼——临时用Cron杀进程是个应急好办法,而且得确保不误杀主进程,下面给你一套靠谱的方案:
一、核心命令:筛选并杀死超时的PHP-FPM子进程
首先要明确:绝对不能杀掉php-fpm: master process主进程,否则整个PHP-FPM服务都会挂掉。我们只针对pool www的子进程,用下面的命令精准筛选并终止运行超过1小时(3600秒)的进程:
ps -eo pid,etimes,cmd | awk '/php-fpm: pool www/ && $2 > 3600 {print $1}' | xargs -r kill -9
命令拆解:
ps -eo pid,etimes,cmd:输出所有进程的 PID(进程号)、运行时长(秒数,etimes是从启动到现在的总秒数)、完整命令行awk '/php-fpm: pool www/ && $2 > 3600 {print $1}':- 匹配所有包含
php-fpm: pool www的子进程(自动排除主进程) - 只保留运行时长超过3600秒的进程,输出它们的PID
- 匹配所有包含
xargs -r kill -9:把筛选出的PID传给kill -9强制终止,-r参数确保如果没有匹配到超时进程,就不会执行空的kill命令(避免报错)
你的进程列表里那些带额外参数(比如-- uid 0 -- gid 0)的pool www进程,这个正则也能正常匹配,不用担心漏杀。
二、把命令加入Cron定时执行
接下来把这个命令加到Cron里,让它自动定期检查。比如每15分钟检查一次(可以根据你的需求调整频率):
- 打开root用户的crontab(用root权限执行才有权限杀进程):
crontab -e
- 添加下面这一行(注意单引号的转义,Cron里单引号需要用
\'转义):
*/15 * * * * /bin/bash -c 'ps -eo pid,etimes,cmd | awk '\''/php-fpm: pool www/ && $2 > 3600 {print $1}'\'' | xargs -r kill -9'
- 保存退出后,Cron会自动加载新任务。
可选:添加日志记录
如果想排查哪些进程被杀死,可以把命令输出重定向到日志文件:
*/15 * * * * /bin/bash -c 'ps -eo pid,etimes,cmd | awk '\''/php-fpm: pool www/ && $2 > 3600 {print $1}'\'' | xargs -r kill -9' >> /var/log/kill_old_phpfpm.log 2>&1
三、重要注意事项
- 先手动测试命令:在执行Cron之前,先单独运行前面的筛选部分,确认输出的PID都是你要杀的子进程:
ps -eo pid,etimes,cmd | awk '/php-fpm: pool www/ && $2 > 3600 {print $1}'
- 权限问题:必须用root用户的crontab执行,普通用户可能没有权限杀其他用户的PHP-FPM进程
- 别依赖临时方案太久:这只是应急手段,一定要排查根源:
- 检查PHP-FPM配置:看看
pm.max_execution_time、pm.process_idle_timeout是不是设置得过于宽松 - 开启PHP-FPM慢日志:在
php-fpm.conf里配置slowlog和request_slowlog_timeout,找到那些运行超时的具体脚本 - 排查外部依赖:很多时候进程挂着是因为等待数据库查询、外部API响应超时,要优化这些环节
- 检查PHP-FPM配置:看看
备注:内容来源于stack exchange,提问作者bhttoan
相关产品推荐
相关产品推荐

