我有一个网站,定期得到大量睡眠的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