需要一种有选择地杀死休眠php进程的方法


Need a way to selectively kill sleeping php processes

我有一个网站,定期得到大量睡眠的php进程。我的主机服务设置了20个并发运行进程的限制。如果超过限制,我的网站就会出现503错误。

这是一个罕见的现象,似乎与访问我的网站的人数没有任何关系。

作为一个保障,我想有一个cron工作与一个php脚本,将杀死php进程已经睡眠超过10分钟。

我有一个php函数,它会杀死所有休眠超过10分钟的MySql进程;

  public function kill_sleeping_mysql_processes()
  {
     $result = $this->db->query("SHOW FULL PROCESSLIST");
    foreach($result->result_array() as $row)
    {
        if ($row['Command'] == "Sleep" && $row['Time'] > 600)
        {
            $this->db->query("KILL {$row['Id']}")
        }
    }
  }

问题是我怎么能做同样的php进程?

我可以用这段代码读取php进程。
exec("ps aux | less", $output);

我可以用这段代码终止特定的php进程如果我有pid;

$pid = 11054;
exec("kill -9 $pid");

但是我如何有选择地杀死已经休眠超过10分钟的php进程?

我胡乱拼凑了一些东西。它不是很优雅,而且有点hack,但它似乎可以工作,尽管我打算在放入cron作业之前进一步测试它。

    public function kill_dormant_php_processes()
    {
        $output_array = array();
        exec("ps aux | grep -v grep", $ps_output);
        array_shift($ps_output);
        if (count($ps_output) > 0)
        {
            $i = 0;
            foreach ($ps_output as $ps) 
            {
                $ps = preg_split('/ +/', $ps);
                $output_array[$i]->pid = $ps[1];
                $output_array[$i]->stat = $ps[7];
                $output_array[$i]->time = $ps[9];
                $i++;
            }
        }
        if( ! empty($output_array))
        {
            foreach ($output_array as $row) 
            {
                if( $row->stat == 'S' && date('H:i', strtotime($row->time)) > date('H:i', strtotime('00:01')))
                {
                    exec("kill -9 $row->pid");
                }
            }
        }
    }

我相信一定有更好的方法来做这件事。

有人能解释一下为什么读出来的00:01似乎翻译成6分钟吗?

freedom   6933  6.0  0.1  57040 13040 ?        S    16:55   0:01 /usr/local/bin/php53.cgi -c .:/home/freedom/:/etc index.php

作为这里共享的PHP脚本的替代方案,您可以使用killall命令和一个"比"更早的时间过滤器(使用-o选项)来终止所有这些进程。

例如,此命令将杀死所有运行超过30分钟的php-cgi进程。

killall -o 30m /usr/bin/php-cgi