#php #exec
#php #exec
Вопрос:
Когда я запускаю exec
из PHP вот так:
$result = exec('command');
Результаты этого будут сохранены в $result
. Но в моем текущем случае моя команда может занять несколько минут и выводит результаты по мере выполнения. Есть ли способ получить выходные данные во время ее выполнения? Я знаю, что passthru
метод будет выводить результаты в браузере, но на самом деле я хочу это напрямую.
Комментарии:
1. возможно использовать CGI вместо PHP?
Ответ №1:
Вам следует взглянуть на proc_open
После того, как выходной поток стал неблокирующим (с stream_set_blocking
), вы можете читать из него, когда захотите, без блокировки вашего PHP-кода.
-Редактировать- Если вы используете
$result = exec('command > /path/to/file amp;');
Она будет выполняться в фоновом режиме, и вы можете прочитать выходные данные в /path/to/file
Ответ №2:
Возможно, не лучший способ сделать это (но сработал для меня):
<?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 processn";
}
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
echo "nnnDonen";
echo "Result is:n----n".$str."n----n";
?>
Ответ №3:
укажите второй аргумент
exec('command', $result);
Если аргумент вывода присутствует, то указанный массив будет
заполняется каждой строкой выходных данных команды. Завершающий
пробелы, такие как n, не включены в этот массив. Обратите внимание, что если
массив уже содержит некоторые элементы, exec() добавит к
конец массива. Если вы не хотите, чтобы функция добавляла элементы,
вызовите unset() для массива перед передачей его в exec().
Комментарии:
1. Спасибо, но, насколько я понимаю, для этого все еще требуется, чтобы exec полностью завершил работу, прежде чем я смогу получить результат. Я специально хочу получить выходные данные во время выполнения команды, чтобы я мог обновить индикатор выполнения.
2. @Zenox: а. в таком случае это невозможно. PHP не является асинхронным
Ответ №4:
Возможно, удастся достичь того, что вам нужно, используя passthru()
в сочетании с буферизацией вывода. Хотя и не уверен.
Ответ №5:
Для тех, кому это может помочь, я использовал ответ Эдди и изменил его для своих целей (вывод файла дампа 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);