получение реального кода выхода после proc_open

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

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

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

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


Обновлять

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


person Daniel Beardsley    schedule 04.10.2011    source источник
comment
Сегодня снова столкнулся с этим и в итоге нашел свой вопрос без ответа во время поиска в Google.   -  person Daniel Beardsley    schedule 06.10.2011


Ответы (2)


Насколько я понимаю, 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;
    }
}

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

person Chad Brogan    schedule 20.10.2011

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

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

$status = proc_get_status($process);
while ($status["running"]) {
  sleep(1);
  $status = proc_get_status($process);
}
person spcurry    schedule 27.01.2012