我有一个 PHP 脚本来运行具有执行时间限制和 cpu 时间限制的命令。
限制.php:
<?php
declare(ticks = 1);
ini_set('display_errors','on');
error_reporting(E_ALL);
if ($argc<2) die("Usage: php ".__FILE__." \"your command here\" [execute_time_limit = 600] [cpu_time_limit = 120]\n");
$cmd = $argv[1];
$tl = isset($argv[2]) ? intval($argv[2]) : 0;
$cl = isset($argv[3]) ? intval($argv[3]) : 0;
if (!$cmd) die("INCORRECT_CMD");
if ($tl<=0) $tl = 600;
if ($cl<=0) $cl = 120;
function sigalrm_handler($signo) {die('EXECUTE_ENDED');}//normal ended or killed by ulimit
$pid = pcntl_fork();
if (-1 == $pid) {
die('FORK_FAILED');
} elseif ($pid == 0) {
exec("ulimit -t $cl && $cmd");
posix_kill(posix_getppid(), SIGALRM);
} else {
pcntl_signal(SIGALRM, 'sigalrm_handler');
sleep($tl);
posix_kill($pid, SIGKILL);
die("TIMEOUT_KILLED : $pid");
}
另一个用于测试的 PHP 脚本。
测试.php
<?php
$i=0;
echo getmypid();
while(1) {
$i++;
file_put_contents("/tmp/x.log",$i."\n",FILE_APPEND);
echo "*";
sleep(1);
}
运行此命令:
php limit.php "php test.php" 10
使用“ps -ef|grep ph[p]”,你可以找到我们预期的被分叉和杀死的进程。
但是当我尝试这个命令时,
php limit.php "php test.php > /tmp/y.log" 10
子进程不能像我们预期的那样被杀死。看:
开始:
================
alix 28979 23528 0 17:32 pts/0 00:00:00 php limit.php php test.php > /tmp/y.log 10
alix 28980 28979 0 17:32 pts/0 00:00:00 php limit.php php test.php > /tmp/y.log 10
alix 28981 28980 0 17:32 pts/0 00:00:00 sh -c ulimit -t 120 && php test.php > /tmp/y.log
alix 28982 28981 0 17:32 pts/0 00:00:00 php test.php
10秒后:
==================
alix 28981 1 0 17:32 pts/0 00:00:00 sh -c ulimit -t 120 && php test.php > /tmp/y.log
alix 28982 28981 0 17:32 pts/0 00:00:00 php test.php
PID 28979 fork 28980,然后函数 exec 创建了 2 个 PID 为 28981 和 28982 的子进程。10 秒后,28979 向 28980 发送 SIGKILL,但 28981 和 28982 没有受到影响(如果没有像 "> /tmp 这样的输出重定向,它们将被杀死/y.log")。
我的服务器是:Linux s4 2.6.18-308.1.1.el5 #1 SMP Wed Mar 7 04:16:51 EST 2012 x86_64 x86_64 x86_64 GNU/Linux With PHP 5.3.9 (cli) (built: Feb 15 2012 11: 54:46)
有什么建议吗?