Живой вывод скрипта Bash, выполненный из PHP

1

Я пытаюсь выполнить скрипт bash из php и получить его вывод в реальном времени.

Я применяю ответы, найденные здесь:

Однако они не работают для меня.

Когда я вызываю скрипт.sh таким образом, он отлично работает:

<?php
  $output = shell_exec("./test.sh");
  echo "<pre>$output</pre>";
?>

Однако при выполнении:

<?php
  echo '<pre>';
  passthru(./test.sh);
  echo '</pre>';
?>

или:

<?php
  while (@ ob_end_flush()); // end all output buffers if any
  $proc = popen(./test.sh, 'r');
  echo '<pre>';
  while (!feof($proc))
    {
    echo fread($proc, 4096);
    @ flush();
    }
  echo '</pre>';
?>

У меня нет вывода в моем браузере.

Я также попытался вызвать переменную вместо сценария в обоих случаях, я имею в виду:

<?php
  $output = shell_exec("./test.sh");
  echo '<pre>';
  passthru($output);
  echo '</pre>';
?>

Это мой скрипт test.sh:

#!/bin/bash
whoami
sleep 3
dmesg
  • 0
    имя файла должно быть заключено в кавычки - passthru("./test.sh"); - это не работает даже так?
  • 0
    @ewcz Это работает с моим примером test.sh, спасибо. Однако это не работает для реального сценария, который я хочу использовать. По крайней мере, это только начало, и теперь я могу анализировать дальше. Если вы напишите свой комментарий как ответ, я проверю его.
Теги:
shell-exec

1 ответ

2
Лучший ответ

Используйте следующее:

<?php
ob_implicit_flush(true);
ob_end_flush();

$cmd = "bash /path/to/test.sh";

$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("pipe", "w")    // stderr is a pipe that the child will write to
);


$process = proc_open($cmd, $descriptorspec, $pipes, realpath('./'), array());

if (is_resource($process)) {

    while ($s = fgets($pipes[1])) {
        print $s;

    }
}

?>

Измените test.sh на:

#!/bin/bash
whoami
sleep 3
ls /

Объяснение:

dmesg требует разрешений. Для этого вам необходимо предоставить права пользователя веб-сервера. В моем случае apache2 запускается через пользователя www-data.

ob_implicit_flush(true): Включает скрытую ob_implicit_flush(true). Неявная промывка приведет к операции флеша после каждого выходного вызова, так что явные вызовы flush() больше не понадобятся.

ob_end_flush(): Отключает буферизацию вывода, поэтому мы сразу видим результаты.

  • 0
    stream_select() + stream_get_contents() лучше подходят для работы, так как fgets() прекращает чтение, когда появляется stream_get_contents() что, скорее всего, произойдет). Проверьте мой предыдущий ответ здесь: stackoverflow.com/a/37526704/1957951

Ещё вопросы

Сообщество Overcoder
Наверх
Меню