PHP proc_open открывается несколько раз - PullRequest
8 голосов
/ 23 января 2011

У меня есть служебная функция, используемая для выполнения программы через CLI (cmd, bash и т. Д.).Он возвращает массив из 3 элементов: STDOUT, STDERR и EXIT CODE.

До сих пор он работал без проблем.На самом деле, проблема, с которой я столкнулся, на самом деле не мешает его функциональности, но я беспокоюсь о производительности.

Проблема в том, что в некоторых случаях PHP выполняет одну и ту же команду несколько раз (в моем случае), даже если он должен был сделать это только один раз.

/**
 * Executes a program and waits for it to finish, taking pipes into account.
 * @param string $cmd Command line to execute, including any arguments.
 * @param string $input Data for standard input.
 * @param boolean $log Whether to log execution failures or not (defaults to true).
 * @return array Array of "stdout", "stderr" and "return".
 */
public static function execute($cmd,$stdin=null,$log=true){
    //static $once=true; if(!$once)die; $once=false;
    $proc=proc_open($cmd, array(
        0=>array('pipe','r'),
        1=>array('pipe','w'),
        2=>array('pipe','w')   ), $pipes);
    fwrite($pipes[0],$stdin);                fclose($pipes[0]);
    $stdout=stream_get_contents($pipes[1]);  fclose($pipes[1]);
    $stderr=stream_get_contents($pipes[2]);  fclose($pipes[2]);
    $return=proc_close($proc);
    if($return!=0 && $log)
        xlog('Error: Program execution returned failure.',$stdout,$stderr,$return);
    return array( 'stdout'=>$stdout, 'stderr'=>$stderr, 'return'=>$return );
}

Обратите внимание на закомментированную строку (строка 9).Это было для тестирования.Я включил его, чтобы целевая программа запускалась только один раз (я думал, что мой код может вызывать ту же функцию как-то).Но даже если эта строка включена, программа все равно запускалась несколько раз.

В моем коде есть 2 места, где я выполняю одну и ту же программу (в разных случаях).Командная строка одинакова для них обоих.

Однако в одном случае программа запускается один раз, в то время как в этом случае PHP запускает программу 3 раза.

Я былМониторинг и просмотр этого поведения в Process Explorer.Я использую Windows 7 x64.Программа 32-битная, как и PHP.

Редактировать: Данная программа разработана специально и не открывает новые процессы.

Ответы [ 3 ]

1 голос
/ 16 мая 2011

Ваш код для проверки того, что он выполняется только один раз, выглядит некорректно.

Если у вас запущено 2 php-процесса, они не будут использовать статическую переменную.Таким образом, возможно, что у вас есть одновременные запросы, которые приводят к тому, что он запускается более одного раза.

Во-вторых, вы должны установить $once в false в конце функции, иначе die никогда не будетдостиг.

Попробуйте добавить запись в журнал, чтобы увидеть, вызывается ли функция дважды.

Создайте несколько модульных / стресс-тестов, которые просто запускают внешнее приложение.Если вы видите несколько процессов, значит в вашем приложении что-то не так, а не код php.

0 голосов
/ 17 мая 2011

Я знаю, что это может быть не самый лучший вариант, но это то, что я сделал.Хотя это было в Linux, но я уверен, что есть способ перенести это на Windows.

То, что я сделал, запустил pgrep и проверил, существует ли уже команда, подобная этой, и просто ли она завершается.Как вы сказали, вы выполняете ту же команду (с точными параметрами), так что просто проверьте, есть ли уже запущенная команда, и действуйте соответственно.

Я использовал эту команду:

$pid = shell_exec('pgrep -cfx "/* My command */"');
if ($pid > 1) return -1;
0 голосов
/ 17 мая 2011

Это очень странно. И это очень трудно понять без полного кода.

Если вы заставляете свой сервер вызывать одну и ту же страницу несколько раз, лучше всего, вероятно, это связано с процессом циклического перебора ЦП. PHP не успевает установить статическую переменную в false, потому что в то же время есть другой запрос к этому методу. Другая возможность заключается в том, что PHP не может должным образом изолировать статическое значение, и другой запрос к этому методу может считывать различные позиции в памяти, пока PHP не синхронизирует значения.

...