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秒后进程退出