我正在使用我编写的包装器类运行一个第三方脚本,它调用shell_exec()并通过管道传输到一个文件中,我稍后会使用php代码进行解析。我应该提到这是有效的,但我正在努力增强功能,因为我遇到了一个我没有想到的用例。
在shell_exec()上管理超时的最佳方法是什么?我正在考虑将它包装在try() catch()中,但我不确定如何最好地处理时间部分。
我在这里读了一些关于shell_exec()和exec()的问题,似乎通过将输出参数传递给exec()可以获得返回,但这确实依赖于脚本以返回状态结束。另外,在我的迷你测试页面中,我似乎不能让它返回任何输出!
我考虑的另一个选择是使用模式对话框,在脚本运行时使用ajax样式的微调器,并在javascript中设置手动超时。然后给用户一个关于它失败/超时和结束的模型对话框消息。
对于这个用例,有没有什么被接受的方法?
我的迷你测试由以下几部分组成:
public $e_return = array();
public $e_status = '';
// Paths are absolute from /
public function execCheck($domain){
exec($this->ssl_check_path." -s ".$domain." -p 443 > ".$this->folder.$this->filename." 2>&1 &", &$this->e_return, &$this->e_status);
}
// Returns
Array
(
)
0使用这个问题作为参考,Can't execute PHP script using PHP exec
http://www.php.net/manual/en/function.exec.php
发布于 2010-08-05 01:15:10
我建议你考虑使用proc_open。您可以将其配置为返回流资源,手动保留定时器,如果定时器在进程结束前超时,可以通过proc_terminate销毁。如果它在计时器到期之前完成,那么您可以使用proc_close,然后使用stream_get_contents来获取原本会写入标准输出的数据。
请参阅http://www.php.net/manual/en/function.proc-open.php
发布于 2012-11-08 19:12:15
我为这样的任务编写了一些有效的代码。函数返回退出代码(0 - OK,>0 -错误),并将stdout,stderr写入引用变量。
/*execute program and write all output to $out
terminate program if it runs more than 30 seconds */
execute("program --option", null, $out, $out, 30);
echo $out;
function execute($cmd, $stdin=null, &$stdout, &$stderr, $timeout=false)
{
$pipes = array();
$process = proc_open(
$cmd,
array(array('pipe','r'),array('pipe','w'),array('pipe','w')),
$pipes
);
$start = time();
$stdout = '';
$stderr = '';
if(is_resource($process))
{
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
fwrite($pipes[0], $stdin);
fclose($pipes[0]);
}
while(is_resource($process))
{
//echo ".";
$stdout .= stream_get_contents($pipes[1]);
$stderr .= stream_get_contents($pipes[2]);
if($timeout !== false && time() - $start > $timeout)
{
proc_terminate($process, 9);
return 1;
}
$status = proc_get_status($process);
if(!$status['running'])
{
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
return $status['exitcode'];
}
usleep(100000);
}
return 1;
}发布于 2016-10-27 19:26:22
我尝试使用popen(),但之后无法终止该进程。此外,即使在Windows上使用stream_set_blocking,stream_get_contents()也会阻止流,所以我不得不使用fread。此外,proc_terminate在Windows上不能正常工作,所以我不得不使用一个替代的kill函数。
我已经想到了这一点,它现在应该可以在Windows和Linux上运行:
function execute($command, $timeout = 5) {
$handle = proc_open($command, [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']], $pipe);
$startTime = microtime(true);
/* Read the command output and kill it if the proccess surpassed the timeout */
while(!feof($pipe[1])) {
$read .= fread($pipe[1], 8192);
if($startTime + $timeout < microtime(true)) break;
}
kill(proc_get_status($handle)['pid']);
proc_close($handle);
return $read;
}
/* The proc_terminate() function doesn't end proccess properly on Windows */
function kill($pid) {
return strstr(PHP_OS, 'WIN') ? exec("taskkill /F /T /PID $pid") : exec("kill -9 $pid");
}https://stackoverflow.com/questions/3407939
复制相似问题