I'm running a third party script by using a wrapper class I've written which calls shell_exec()
and pipes into a file I parse later using php code. I should mention that this is working, but I am trying to enhance the functionality, having encountered a use case I hadn't thought of.
How is it best to manage timeout on shell_exec()? I was thinking of wrapping it in a try() catch()
but I'm not sure how to best handle the time component.
I've been reading a few questions on here relating to shell_exec()
and exec()
and it seems that by passing output params to exec()
you can get a return, but that does rely on the script finishing with a return status. Plus in my mini test page, I can't seem to get it to return any output!
The other option I thought about was using a modal dialog, with an ajax style spinner whilst the script it working, and setting a manual timeout in javascript. Which then gave the user a model dialog message about it failing/timeout and ending.
Are there any accepted methods for this use case?
My mini test, consisted of the following,
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
Using this question as ref, Can't execute PHP script using PHP exec
http://www.php.net/manual/en/function.exec.php
I write some working piece of code for such task. Function returns exit code (0 - OK, >0 - error) and writes stdout, stderr to reference variables.
/*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;
}
I would suggest you look into using proc_open
. You can configure it to return a stream resource, manually keep a timer, and if the timer expires before the process completes, you can terminate it with proc_terminate
. If it does complete before the timer expires, then you can use proc_close
then stream_get_contents
to grab the data that would have otherwise been written to stdout.
See http://www.php.net/manual/en/function.proc-open.php
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With