1

i have tried many time by using flush() to make the script work synchronously, the script prints only data of the first command "gcloud compute ssh yellow" and "ls -la", I am looking to make the script prints the output on every executed fputs().

<?php

$descr = array( 0 => array('pipe','r',),1 => array('pipe','w',),2 => array('pipe','w',),);
$pipes = array();
$process = proc_open("gcloud compute ssh yellow", $descr, $pipes);

if (is_resource($process)) {
    sleep(2);
    $commands = ["ls -la", "cd /home", "ls", "sudo ifconfig", "ls -l"];     
    foreach ($commands as $command) {    
        fputs($pipes[0], $command . " \n");
        while ($f = fgets($pipes[1])) {
            echo $f;
        }
    }
    fclose($pipes[0]);  
    fclose($pipes[1]);
    while ($f = fgets($pipes[2])) {
        echo "\n\n## ==>> ";
        echo $f;
    }
    fclose($pipes[2]);
    proc_close($process);

}

Thanks in advance

miken32
  • 42,008
  • 16
  • 111
  • 154
Ely
  • 13
  • 6

1 Answers1

0

I believe the problem is the loop you have waiting for input. fgets will only return false if it encounters EOF. Otherwise it returns the line that it read; because the linefeed is included, it doesn't return anything that can be typecast to false. You can use stream_get_line() instead, which does not return the EOL character. Note this would still require your command to return an empty line after its output so it can evaluate to false and break the while loop.

<?php
$prog     = "gcloud compute ssh yellow";
$commands = ["ls -la", "cd /home", "ls", "sudo ifconfig", "ls -l"];
$descr    = [0 => ['pipe','r'], 1 => ['pipe','w'], 2 =>['pipe','w']];
$pipes    = [];
$process  = proc_open($prog, $descr, $pipes);

if (is_resource($process)) {
    sleep(2);
    foreach ($commands as $command) {
        fputs($pipes[0], $command . PHP_EOL);
        while ($f = stream_get_line($pipes[1], 256)) {
            echo $f . PHP_EOL;
        }
    }
    fclose($pipes[0]);
    fclose($pipes[1]);
    fclose($pipes[2]);
    proc_close($process);
}

Another option would be to gather the output outside the loop, although this would require you to parse the output if you need to know what output came from what command.

<?php
$prog     = "gcloud compute ssh yellow";
$commands = ["ls -la", "cd /home", "ls", "sudo ifconfig", "ls -l"];
$descr    = [0 => ['pipe','r'], 1 => ['pipe','w'], 2 =>['pipe','w']];
$pipes    = [];
$process  = proc_open($prog, $descr, $pipes);

if (is_resource($process)) {
    sleep(2);
    foreach ($commands as $command) {
        fputs($pipes[0], $command . PHP_EOL);
    }
    fclose($pipes[0]);
    $return = stream_get_contents($pipes[1]);
    $errors = stream_get_contents($pipes[2]);
    fclose($pipes[1]);
    fclose($pipes[2]);
    proc_close($process);
}
miken32
  • 42,008
  • 16
  • 111
  • 154
  • The first code still doesn't print the full output of the other commands, the last one prints the full output and works perfectly, My goal is to make it live output with no issues. thank you Mr Miken32 – Ely Dec 05 '18 at 12:43