2

I'm trying to read information from the command line via exec();

function ex($cmd){

    @exec($cmd,$exec,$status);

    if($status == 0){
        return $exec;   
    }
    return "";

}

I'm trying to parse the output "line by line" but the problem is that the output lines are splitted (just as if the terminal window is "too small"). For parsing it would be pretty helpful if there is no "line length limit" for the output and one line keeps one line no matter what size it is.

How can I archive that?

Daniel K.
  • 1,189
  • 1
  • 10
  • 26
  • What command are you running? Most commands don't care about the window size, especially if output is not directed to a terminal. – Barmar Jul 08 '14 at 16:06
  • 2
    Try `putenv("COLUMNS=1000");` before calling `exec`. – Barmar Jul 08 '14 at 16:12
  • I'm running `apt-get --just-print upgrade` and I just tried the "putenv" but it did not change anything :( – Daniel K. Jul 15 '14 at 12:16
  • Not sure if this helps but is there a chance to pipe the output of `apt-get upgrade --justprint` to `cat` or something like this? To see the problem you could try the following: Reize the window to about 20 columns and run the command. Afterwards resize it to about 200 columns. The other way around it works perfect of course. – Daniel K. Jul 15 '14 at 12:32
  • can you please mention what you want and what you get? – Man Programmer Jul 21 '14 at 09:28
  • As already described above I want to "parse" the output of ´apt-get --just-print upgrade´. When running this command from PHP and there are lots of upgrades available the output placed in different lines which makes parsing a little bit harder since I don't know how many lines are related to that output line. So I want to have them all on one line as it usually is when you run this command in a large terminal window. You can see what's the issue if you try running the command as described above. – Daniel K. Jul 21 '14 at 09:34
  • Is you want to store apt-get --just-print upgrade output in file – Man Programmer Jul 21 '14 at 09:39
  • Not really but maybe it's a solution to pipe the output into a temp file and read this file in the parser! I'll give that a try! – Daniel K. Jul 21 '14 at 11:52
  • Doesn't work. Output has even more "cuts" in it as before. – Daniel K. Jul 26 '14 at 12:57
  • 1
    `apt-get` needs to have a width to print its progress bar: how it would work otherwise? If you want to capture its output for your own purposes I would use at least the **-q** option to disable the progress bar. – ntd Jul 27 '14 at 13:31
  • Good explanation. Seems legit ;) But sadly it doesn't solve the problem. Anyway +1 for the idea. – Daniel K. Jul 27 '14 at 14:18

4 Answers4

1

A workaround with proc_open(). It's expensive, but this should give you the exact output from your command:

<?php
$descriptorspec = array(
   0 => array("pipe", "r"),
   1 => array("pipe", "w")
);

$shell = '/bin/bash';
$command = 'apt-get --just-print upgrade';

$process = proc_open($shell, $descriptorspec, $pipes);

if (is_resource($process)) {

    fwrite($pipes[0], $command);
    fclose($pipes[0]);

    $output = stream_get_contents($pipes[1]);
    fclose($pipes[1]);

    proc_close($process);
}

//$output holds the output in a single string

$lines = explode("\n", $output); // the full lines as array
marfis
  • 278
  • 1
  • 8
0

Why you don't use exec directly and get its output. For example

$output=exec("ls -la");

Then you can study the output like you want:

$lines = explode("\n",$output);
foreach($lines as $line)
   echo $line."<br>";

By other hand, you could use the passtrhu function http://php.net/manual/en/function.passthru.php

Javier Gálvez
  • 166
  • 1
  • 11
  • Well that's does not change the problem since there are "\n" in the output that I don't want to be there because of the parsing problems (they are there because the "terminal" is to small which does not say anything about the content). – Daniel K. Jul 24 '14 at 11:46
  • Did you try to save the command in a file and then study it?, for example `ls -la > myFile.txt`. Other option is to do an array of substrings and then concat them. I ask which type of terminal do you use to have this problem, because php cli doesn't matter about the size of the screen. – Javier Gálvez Jul 24 '14 at 14:48
  • Tried the "put into file" solution but the lines are even "smaller" than the output of exec/shell_exec() – Daniel K. Jul 26 '14 at 12:58
  • Did you try to remove "\n" in the resulting file with the sed command. http://stackoverflow.com/questions/1251999/sed-how-can-i-replace-a-newline-n – Javier Gálvez Jul 28 '14 at 09:46
0

You can run it with shell_exec returns all of the output stream as a string. On the other hand exec only returns the last line of the output.

<?php

function ex($cmd) {
    return explode("\n", shell_exec($cmd));
}

$output = ex('apt-get --just-print upgrade');

var_dump($output);
Adrià Cidre
  • 392
  • 3
  • 3
  • I already get single lines but the output is split in single lines which is kind of an "unexpected" behaviour. – Daniel K. Jul 26 '14 at 13:00
0

Since the other solutions don't fix the problem or have high costs I used the following code which is not very generic but solves the problem:

$str = ""; $versions['upgrades'] = array(); $addLines = 0;

for($i = 0; $i < count($v); $i++){
    if(preg_match("~[0-9]+ upgraded~",$v[$i])){
        $str = $v[$i];
        break;
    }
    if($addLines == 1){
        $versions['upgrades'] = array_merge($versions['upgrades'],array_values(explode(' ',trim($v[$i]))));
    }
    if(preg_match("~will be upgraded~",$v[$i])){
        $addLines = 1;
    }
}
Daniel K.
  • 1,189
  • 1
  • 10
  • 26