За последние 24 часа нас посетил 21431 программист и 1694 робота. Сейчас ищут 1810 программистов ...

proc_open и множественные записи в STDIN открытого процесса

Тема в разделе "Прочие вопросы по PHP", создана пользователем lexand, 15 мар 2010.

  1. lexand

    lexand Активный пользователь

    С нами с:
    14 апр 2009
    Сообщения:
    6
    Симпатии:
    0
    Адрес:
    Украина
    Здравствуйте.

    ОС: Ubuntu Server 9.10 x64
    PHP: 5.2.10-2ubuntu6.4

    Код (Text):
    1.  
    2. header('Content-Type: text/plain');
    3.  
    4. $descriptorspec = array(
    5.    0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
    6.    1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
    7.    2 => array("pipe", "w") // stderr is a file to write to
    8. );
    9.  
    10. $conn = proc_open('ftp', $descriptorspec, $pipes);
    11.  
    12. if (is_resource($conn)) {
    13.  
    14.     $wh = &$pipes[0];
    15.     $rh = &$pipes[1];
    16.     $eh = &$pipes[2];
    17.     stream_set_blocking($eh, false);
    18.  
    19.     sleep(1);
    20.  
    21.     // читатем все что программа вывела при запуске и игнорируем - странно то что все равно ничего не получаем
    22.     // даже строку приглашения [b]ftp >[/b]
    23.     stream_set_blocking($rh, false);
    24.     echo "Response:\n".stream_get_contents($rh);
    25.     stream_set_blocking($rh, true);
    26.  
    27.     fwrite($wh, "help");
    28.     fclose($wh);
    29.     echo "Error:\n".stream_get_contents($eh); // пустой
    30.     echo "Response:\n".stream_get_contents($rh); // список команд
    31.  
    32.     foreach($pipes as $pipe) @fclose($pipe);
    33.  
    34.     $return_value = proc_close($conn);
    35.     echo "command returned $return_value\n";
    36. }
    37. ?>
    этот скрипт работает, но мне к сожалению нужно иметь возможность отсылать не одну команду а много, тоесть не закрывать каждый раз pipe после использования.

    Код (Text):
    1.  
    2. header('Content-Type: text/plain');
    3.  
    4. $descriptorspec = array(
    5.    0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
    6.    1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
    7.    2 => array("pipe", "w") // stderr is a file to write to
    8. );
    9.  
    10. $conn = proc_open('ftp', $descriptorspec, $pipes);
    11.  
    12. if (is_resource($conn)) {
    13.  
    14.     $wh = &$pipes[0];
    15.     $rh = &$pipes[1];
    16.     $eh = &$pipes[2];
    17.     stream_set_blocking($eh, false);
    18.  
    19.     sleep(1);
    20.  
    21.     // читатем все что программы вывела при запуске и игнорируем
    22.     stream_set_blocking($rh, false);
    23.     echo "Response:\n".stream_get_contents($rh);
    24.     stream_set_blocking($rh, true);
    25.  
    26.     fwrite($wh, "help\n");
    27.     fflush($wh);
    28.     sleep(1);
    29.     echo "Error:\n".stream_get_contents($eh);
    30.     echo "Response:\n".stream_get_contents($rh); // дальше этого скрипт не выполняется
    31.  
    32.     fwrite($wh, "open ftp.some.domain\n");
    33.     fflush($wh);
    34.     sleep(1);
    35.     echo "Error:\n".stream_get_contents($eh);
    36.     echo "Response:\n".stream_get_contents($rh);
    37.  
    38.  
    39.     foreach($pipes as $pipe) @fclose($pipe);
    40.  
    41.     $return_value = proc_close($conn);
    42.     echo "command returned $return_value\n";
    43. }
    44. ?>
    этот скрипт не работает - он блокируется на первом echo "Response:\n".stream_get_contents($rh);, ожидает поступления даннных на $rh.

    чтобы скриптец не блокировался есть два варианта
    1. который уже не подходит - использовать fclose вместо fflush, тогда естественно вторая команда не выполнится. И придется каждый раз открывать процеес для новой команды.
    2. отменить блокировку для $rh - скрипт не блокируется, но команды все равно не выполняются и приходят пустые ответы

    посмотрел все примеры в документации - они для меня не работают.

    теперь вопросы:
    1. можно ли вообще PHP c proc_open использовать для такого интерактивного взаимодействия
    2. может ли команда ftp ожидать еще какойто символ (черт знает какой - может EOF). что то типа fwrite($wh, 'help\n\z');
    3. что еще может быть не правильно, может гдето INI файл поправить нужно.... уже даже не знаю что и предположить

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

    AterCattus Активный пользователь

    С нами с:
    6 фев 2008
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Код (Text):
    1. $read = array( $rh );
    2. $write = NULL;
    3. $except = NULL;
    4. stream_select( $pipes_array, $write, $except, 0 );
     
  3. Hight

    Hight Старожил
    Команда форума Модератор

    С нами с:
    5 мар 2006
    Сообщения:
    7.153
    Симпатии:
    0
    Адрес:
    из злой параллельной вселенной
    lexand
    аватарку на фото смените или удалите
     
  4. lexand

    lexand Активный пользователь

    С нами с:
    14 апр 2009
    Сообщения:
    6
    Симпатии:
    0
    Адрес:
    Украина
    а тут нет ошибочки
    может

    Код (Text):
    1.  
    2. ...
    3. stream_select( $read, $write, $except, 0 );[/quote]
    я помню ковырялся с stream_select, но что то не вішло тогда наверно нужно еще раз попробовать