получить реальный код выхода после proc_open - PullRequest
7 голосов
/ 04 октября 2011

Я использую proc_open в php для запуска подпроцесса и отправки данных туда и обратно.

В какой-то момент я бы хотел дождаться окончания процесса и получить код выхода .

Проблема в том, что если процесс уже завершен , мой вызов proc_close возвращает -1. Очевидно, существует большая путаница по поводу того, что на самом деле возвращает proc_close, и я не нашел способа надежно определить код завершения процесса, открытого с помощью proc_open.

Я пытался использовать proc_get_status, но, похоже, он также возвращает -1, когда процесс уже завершен.


Обновление

Я не могу получить от proc_get_status до правильного кода выхода , независимо от того, как и когда он вызывается. Это сломано полностью?

Ответы [ 2 ]

10 голосов
/ 21 октября 2011

Насколько я понимаю, proc_close никогда не даст вам действительный код выхода.

Вы можете получить только действительный код выхода в первый раз , когда вы запустите proc_get_status после процесс закончился.Вот класс процесса, который я украл из заметок пользователя php.net.Ответ на ваш вопрос в методе is_running ():

<?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;
    }
}

Надеюсь, это поможет.

2 голосов
/ 28 января 2012

Я также получал неожиданные результаты, пытаясь получить код возврата через proc_get_status, пока не понял, что получаю код возврата последней команды, которую я выполнил (я передавал серию команд в proc_open, разделенныхby;).

Как только я разбил команды на отдельные вызовы proc_open, я использовал следующий цикл для получения правильного кода возврата.Обратите внимание, что обычно код выполняется proc_get_status дважды, и правильный код возврата возвращается при втором выполнении.Кроме того, приведенный ниже код может быть опасным, если процесс никогда не завершится.Я просто использую это как пример:

$status = proc_get_status($process);
while ($status["running"]) {
  sleep(1);
  $status = proc_get_status($process);
}
...