Предпосылки: Я пытаюсь написать сценарий оболочки с помощью php, который автоматически проверяет несколько крупных SVN-репозиториев. Я также использую класс индикаторов консоли PEAR, чтобы отобразить ход проверки (не совсем необходимый, но то, что вызвало мой вопрос).
Вопрос: Есть ли способ запустить цикл, который будет обновляться при каждом выходе строки в STDIN в командной строке?
Если я сделаю
<?php shell_exec("svn co svn://my.repo.com/repo/trunk"); ?>
Я возвращаю весь вывод команды из гигантской строки. Попытка цикла
<?php $bar = new Console_ProgressBar('%fraction% [%bar%] %percent% | %elapsed% :: %estimate%', '=>', ' ', 80, $total); $bar->display(0); stream_set_blocking(STDIN, 0); $output = array(); $return = ''; exec("svn co $svnUrl $folder", $output, $return); while (!isset($return)) { $bar->update(count($output)); } $bar->erase(); ?>
отобразит панель, но не обновится.
Любые решения?
========================= ОБНОВЛЕНИЕ ========================================================== ===============
Вот рабочий код, который я придумал на основе ответа (для дальнейшего использования):
<?php $bar = new Console_ProgressBar('%fraction% [%bar%] %percent% | %elapsed% :: %estimate%', '=>', ' ', 80, $total); $handle = popen("/usr/bin/svn co $svnUrl $folder", 'r'); $elapsed = 0; $bar->display($elapsed); while ($line = fgets($handle)) { $elapsed++; $bar->update($elapsed); } pclose($handle); ?>
PHP не многопоточен. exec (), и компания заблокирует ваш скрипт до завершения задачи exec'd. Нет смысла использовать цикл while (), потому что цикл даже не запускается до тех пор, пока вызов svn не завершится.
Если вы хотите запустить несколько параллельных svn, вам нужно будет использовать popen () (или proc_open () ), который дает вам дескриптор файла, из которого вы можете прочитать вывод внешней команды, и одновременно иметь несколько таких внешних команд ,
Использовать буферизацию вывода
видеть:
и см. некоторые связанные:
AS Я понимаю вашу проблему, что php выполняет скрипт синхронно. Это означает, что цикл будет запускаться только после команды exec, и выход не будет изменен, поскольку он уже выполнен. Попробуйте использовать вилку.