I'm using proc_open
in php to launch a subprocess and send data back and forth.
At some point I'd like to wait for the process to end and retrieve the exit code.
The problem is that if the process has already finished, my call to proc_close
returns -1. There is apparently much confusion over what proc_close
does actually return and I haven't found a way to reliably determine the exit code of a process opened with proc_open
.
I've tried using proc_get_status
, but it seems to also return -1 when the process has already exited.
I can't get proc_get_status
to ever give me a valid exit code, no matter how or when it is called. Is it broken completely?.
My understanding is that proc_close
will never give you a legit exit code.
You can only grab the legit exit code the first time you run proc_get_status
after the process has ended. Here's a process class that I stole off the php.net user contributed notes. The answer to your question is in the is_running() method:
<?php
class process {
public $cmd = '';
private $descriptors = array(
0 => array('pipe', 'r'),
1 => array('pipe', 'w'),
2 => array('pipe', 'w')
);
public $pipes = NULL;
public $desc = '';
private $strt_tm = 0;
public $resource = NULL;
private $exitcode = NULL;
function __construct($cmd = '', $desc = '')
{
$this->cmd = $cmd;
$this->desc = $desc;
$this->resource = proc_open($this->cmd, $this->descriptors, $this->pipes, NULL, $_ENV);
$this->strt_tm = microtime(TRUE);
}
public function is_running()
{
$status = proc_get_status($this->resource);
/**
* proc_get_status will only pull valid exitcode one
* time after process has ended, so cache the exitcode
* if the process is finished and $exitcode is uninitialized
*/
if ($status['running'] === FALSE && $this->exitcode === NULL)
$this->exitcode = $status['exitcode'];
return $status['running'];
}
public function get_exitcode()
{
return $this->exitcode;
}
public function get_elapsed()
{
return microtime(TRUE) - $this->strt_tm;
}
}
Hope this helps.
I also was getting unexpected results trying to get the return code via proc_get_status
, until I realized I was getting the return code of the last command I had executed (I was passing a series of commands to proc_open
, separated by ;).
Once I broke the commands into individual proc_open
calls, I used the following loop to get the correct return code. Note that normally the code is executing proc_get_status
twice, and the correct return code is being returned on the second execution. Also, the code below could be dangerous if the process never terminates. I'm just using it as an example:
$status = proc_get_status($process);
while ($status["running"]) {
sleep(1);
$status = proc_get_status($process);
}
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