php执行程序可设置超时时间,linux下可用
版权声明:
本文为博主原创文章,转载请声明原文链接...谢谢。o_0。
更新时间:
2021-01-15 20:02:47
温馨提示:
学无止境,技术类文章有它的时效性,请留意文章更新时间,如发现内容有误请留言指出,防止别人"踩坑",我会及时更新文章
使用php执行外部命令并且取返回值,可设置超时时间,如果超时则中止进程
/**
* 执行命令行程序,直到超时退出,只支持linux
* @param string $cmd 命令行程序
* @param string $stdin 标准输入
* @param int $timeout 时间时间秒
* @return array 输出命令结果和错误内容
* @throws Exception
*/
function exec_timeout(string $cmd, string $stdin, int $timeout): array
{
// 传递给进程的标准描述符
$descriptors = array(
0 => array('pipe', 'r'), // stdin
1 => array('pipe', 'w'), // stdout
2 => array('pipe', 'w') // stderr
);
// 启动进程
$process = proc_open($cmd, $descriptors, $pipes);
if (!is_resource($process)) {
throw new \Exception('Could not execute process');
}
//如果有标准输入内容的话就写入
if ($stdin) {
fwrite($pipes[0], $stdin);
}
fclose($pipes[0]);
// 设置标准输出异步不阻塞
stream_set_blocking($pipes[1], 0);
// 设置标准错误输出异步不阻塞
stream_set_blocking($pipes[2], 0);
// 时间时间转为微妙
$timeout = $timeout * 1000000;
// 标准输出内容
$buffer = '';
// 一直等待到超时退出或执行完自动退出
while ($timeout > 0) {
$start = microtime(true);
// Wait until we have output or the timer expired.
$read = array($pipes[1]);
$other = array();
stream_select($read, $other, $other, 0, $timeout);
// Get the status of the process.
// Do this before we read from the stream,
// this way we can't lose the last bit of output if the process dies between these functions.
$status = proc_get_status($process);
// Read the contents from the buffer.
// This function will always return immediately as the stream is non-blocking.
$buffer .= stream_get_contents($pipes[1]);
if (!$status['running']) {
// Break from this loop if the process exited before the timeout.
break;
}
// Subtract the number of microseconds that we waited.
$timeout -= (microtime(true) - $start) * 1000000;
}
// Check if there were any errors.
$errors = stream_get_contents($pipes[2]);
// if (!empty($errors)) {
// throw new \Exception($errors);
// }
// Kill the process in case the timeout expired and it's still running.
// If the process already exited this won't do anything.
proc_terminate($process, 9);
// Close all streams.
// fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
return [
'error' => $errors,
'result' => $buffer
];
}调用执行一个php的死循环
$code = <<<eot
\$i=0;
while(true){
echo \$i++,PHP_EOL;
sleep(1);
}
eot;
$res = exec_timeout('php -a ', $code, 5);
//替换掉开头的输出和空行
$res['result'] = preg_replace('@Interactive shell\s*\n\s*\n@', '', $res['result']);
print_r($res);5秒后进程退出
