Перейти до змісту
  • Головна
  • hamilok

    Користувач
    • Постів

      611
    • Зареєстровано

    • Відвідування

    Активність репутації

    1. Понизити
      hamilok отримав реакцію от Clintonzex в Proc_open & Interactive Communication   
      Задача: программно выполнять утилитную рутину в ОС. Посмотрим на пример с офф. документации:

      $descriptorspec = array( 0 => array("pipe", "r"), // stdin is a pipe that the child will read from 1 => array("pipe", "w"), // stdout is a pipe that the child will write to 2 => array("file", "/tmp/error-output.txt", "a") // stderr is a file to write to ); $cwd = '/tmp'; $env = array('some_option' => 'aeiou'); $process = proc_open('php', $descriptorspec, $pipes, $cwd, $env); if (is_resource($process)) { // $pipes now looks like this: // 0 => writeable handle connected to child stdin // 1 => readable handle connected to child stdout // Any error output will be appended to /tmp/error-output.txt fwrite($pipes[0], '<?php print_r($_ENV); ?>'); fclose($pipes[0]); echo stream_get_contents($pipes[1]); fclose($pipes[1]); // It is important that you close any pipes before calling // proc_close in order to avoid a deadlock $return_value = proc_close($process); echo "command returned $return_value\n"; }Чего же в нем не хватает для интерактивной работы с программой? Правильно! Не закрывать поток ввода и вывода, для выполнения одной или более операций за один запуск нашего скрипта. Но давайте посмотрим что будет если не закрывать потоки. Хм... скрипт завис?! Почему? Все правильно, потоки при создании блокируются. Ничего страшного, исправим:
      ... $process = proc_open('php', $descriptorspec, $pipes, $cwd, $env); // new stream_set_blocking($pipes[1], false); stream_set_blocking($pipes[2], false); ...А теперь что? Функция stream_get_contents возращает пустой результат! И это естественно, так как мы сняли блокировку с потока вывода, и чтение из него не всегда будет давать результат. По этому напишем следующую функцию:
      /** * Данная функция пытается получить результат из потока, * до тех пор пока не закончится количество попыток или не возникнет ошибка. * / function result(&$pipes, $attempt = 5)) { $result = stream_get_contents($pipes[1]); if ($result === false || empty($result) { // Смотрим на ошибки $error = stream_get_contents($pipes[2]); if (!empty($error)) { return false; } // Если в наш еще один шанс :) if ($attempt-- > 0) { sleep(1); return stream_read($pipes, $attempt); } return false; } return $result; }Есть еще один момент. В конце каждой комманды нужно ставить перенос, для этого напишем функцию выполнения комманды:
      function command(&$pipes, $comm) { fwrite($pipes[0], $comm . PHP_EOL); return result($pipes); }Enjoy!
    ×
    ×
    • Створити...

    Важлива інформація

    Використовуючи цей сайт, Ви погоджуєтеся з нашими Умови використання, Політика конфіденційності, Правила, Ми розмістили cookie-файлы на ваш пристрій, щоб допомогти зробити цей сайт кращим. Ви можете змінити налаштування cookie-файлів, або продовжити без зміни налаштувань..