Когда я запускаю exec
из PHP следующим образом:
$result = exec('command');
Результаты этого будут сохранены в $result
. Но в моем текущем случае моя команда может занять несколько минут и выводит результаты по мере ее запуска. Есть ли способ получить выход во время его работы? Я знаю, что метод passthru
выводит результаты как браузер, но я действительно хочу его напрямую.
Вы должны взглянуть на proc_open
После того, как поток потока не блокируется (с stream_set_blocking
), вы можете читать его, когда захотите, без блокировки вашего PHP-кода.
-Edit- Если вы используете
$result = exec('command > /path/to/file &');
Он будет работать в фоновом режиме, и вы можете прочитать вывод в / path / to / file
Возможно, это не лучший способ сделать это (но работал для меня):
<?php $cmd = "ping 127.0.0.1 -c 5"; //example command $descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "a") ); $pipes = array(); $process = proc_open($cmd, $descriptorspec, $pipes, null, null); echo "Start process:\n"; $str = ""; if(is_resource($process)) { do { $curStr = fgets($pipes[1]); //will wait for a end of line echo $curStr; $str .= $curStr; $arr = proc_get_status($process); }while($arr['running']); }else{ echo "Unable to start process\n"; } fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); echo "\n\n\nDone\n"; echo "Result is:\n----\n".$str."\n----\n"; ?>
в<?php $cmd = "ping 127.0.0.1 -c 5"; //example command $descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "a") ); $pipes = array(); $process = proc_open($cmd, $descriptorspec, $pipes, null, null); echo "Start process:\n"; $str = ""; if(is_resource($process)) { do { $curStr = fgets($pipes[1]); //will wait for a end of line echo $curStr; $str .= $curStr; $arr = proc_get_status($process); }while($arr['running']); }else{ echo "Unable to start process\n"; } fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); echo "\n\n\nDone\n"; echo "Result is:\n----\n".$str."\n----\n"; ?>
указать второй аргумент
exec('command', $result);
Если выходной аргумент присутствует, то указанный массив будет заполнен каждой строкой вывода из команды. Пронумерованные пробелы, такие как \ n, не включаются в этот массив. Обратите внимание: если массив уже содержит некоторые элементы, exec () добавит в конец массива. Если вы не хотите, чтобы функция добавляла элементы, вызовите функцию unset () в массиве, прежде чем передать ее в exec ().
Возможно, вы сможете достичь того, что вам нужно, используя passthru()
сочетании с выходной буферизацией . Не уверен.
Для тех, кому это может помочь, я использовал ответ Эдди и изменил его для своих целей (вывод файла дампа MySQL без наводнения ОЗУ сервера)
$dumpCommand = "mysqldump --skip-lock-tables -u $dbuser -p$dbpasswd $dbname"; $dumpFileName = 'backup_'.$dbname.'-'.date('Ymd-Hi').'.sql'; $descriptorSpec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "a") ); $pipes = array(); $process = proc_open($dumpCommand, $descriptorSpec, $pipes, null, null); if(!is_resource($process)) { die('Unable to start process'); } header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="'.$dumpFileName.'"'); do { echo fgets($pipes[1]); // Will wait for EOL $arrStatus = proc_get_status($process); } while($arrStatus['running']); fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process);