3

I'm trying to execute a bash script from php and getting its output in real time.

I am applying the answers found here:

However they are not working for me.

When I invoke the .sh script on this way, it works fine:

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

However, when doing:

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

or:

<?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>'; ?> 

I have no output in my browser.

I also tried to call the variable instead of the script in both cases, I mean:

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

This is my test.sh script:

#!/bin/bash whoami sleep 3 dmesg 
2
  • the filename should be quoted - passthru("./test.sh"); - it doesn't work even like this? Commented Feb 27, 2017 at 13:04
  • @ewcz It does work with my test.sh example, thanks. However it doesn't work for the actual script I want to use. At least this is a beginning and I can analyze further from now on. If you write your comment as answer I will validate it. Commented Feb 27, 2017 at 13:26

1 Answer 1

5

Use the following:

<?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; } } ?> 

Change test.sh to:

#!/bin/bash whoami sleep 3 ls / 

Explanation:

dmesg requires permissions. You need to grant webserver's user permissions for that. In my case apache2 is being run via www-data user.

ob_implicit_flush(true): Turns implicit flushing on. Implicit flushing will result in a flush operation after every output call, so that explicit calls to flush() will no longer be needed.

ob_end_flush(): Turns off output buffering, so we see results immediately.

Sign up to request clarification or add additional context in comments.

1 Comment

stream_select() + stream_get_contents() are better suited for the job, since fgets() stops reading when a newline comes (which is very likely to happen). Check my previous answer here: stackoverflow.com/a/37526704/1957951

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.