如果我使用shell_exec()
外部程序(unix)执行并且它的工作时间超过30秒,则PHP会因致命错误而死亡。那是因为外部程序被绞死/坠毁或者我不知道。
我想抓住这个错误。 try{}..catch{}
在这里不起作用。如何判断外部程序是否已被挂起?通常我的外部程序运行不到2秒。
答案 0 :(得分:0)
您可以使用源代码分发中包含的“run-tests.php”脚本中定义的此函数system_with_timeout
:
(键是传递给stream_select
的最后一个参数)
function system_with_timeout($commandline, $env = null, $stdin = null)
{
global $leak_check, $cwd;
$data = b'';
$bin_env = array();
foreach((array)$env as $key => $value) {
$bin_env[(binary)$key] = (binary)$value;
}
$proc = proc_open($commandline, array(
0 => array('pipe', 'r'),
1 => array('pipe', 'w'),
2 => array('pipe', 'w')
), $pipes, $cwd, $bin_env, array('suppress_errors' => true, 'binary_pipes' => true));
if (!$proc) {
return false;
}
if (!is_null($stdin)) {
fwrite($pipes[0], (binary) $stdin);
}
fclose($pipes[0]);
$timeout = $leak_check ? 300 : (isset($env['TEST_TIMEOUT']) ? $env['TEST_TIMEOUT'] : 60);
while (true) {
/* hide errors from interrupted syscalls */
$r = $pipes;
$w = null;
$e = null;
$n = @stream_select($r, $w, $e, $timeout);
if ($n === false) {
break;
} else if ($n === 0) {
/* timed out */
$data .= b"\n ** ERROR: process timed out **\n";
proc_terminate($proc);
return $data;
} else if ($n > 0) {
$line = (binary) fread($pipes[1], 8192);
if (strlen($line) == 0) {
/* EOF */
break;
}
$data .= $line;
}
}
$stat = proc_get_status($proc);
if ($stat['signaled']) {
$data .= b"\nTermsig=" . $stat['stopsig'];
}
$code = proc_close($proc);
return $data;
}
通过传递这样的数组来给出超时:array('TEST_TIMEOUT' => 200)
作为第二个参数。