Search code examples
phpprocessechoproc-open

PHP Use proc_open and capture stdout of 'echo' command


I've been searching around but haven't managed to find a direct answer to this question. At the outset I'll state that what I'm trying to achieve isn't necessarily particularly useful but the aim is partly to understand how PHP interacts with other processes and streams, etc.

At a shell terminal, you can run a command like echo $USER for example and it will output whatever is in the environment variable called USER.

I'm wondering if it's possible to execute this command and then capture the output from shell echo command using PHP's proc_open function.

This is what I'm trying at the moment:

$descriptors = [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']];
$handle = proc_open('echo Hello world, $USER!', $descriptors, $pipes, null, ['USER' => 'guest']);
$world = stream_get_contents($pipes[0]);

$world is staying empty (i.e. '').

I have a couple of theories as to why it isn't working [as well as a reason why each theory might be false following in square brackets] but I'm wondering if someone could either confirm one of them or offer another explanation as to why it's not working please?


Theory 1 The echo command terminates immediately before PHP has a chance to read the output. [Really? Is there no way to use proc_open to capture output from a command that terminates immediately? Maybe that's not what proc_open is for?]

Theory 2 echo is somehow treated as a shell built-in command rather than a standalone executable and that's why it behaves differently? [Linux provides an executable called echo in /bin/echo, couldn't it just use that one? Plus changing echo to /bin/echo doesn't solve the problem either]


Thank you in advance


Solution

  • You're reading from $pipes[0]. This is stdin. You want to read from $pipes[1] which is mapped to stdout (and has the w flag for being written to):

    $descriptors = [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']];
    $handle = proc_open('echo Hello world, $USER!', $descriptors, $pipes, null, ['USER' => 'guest']);
    $world = stream_get_contents($pipes[1]);
    var_dump($world);
    

    Outputs

    string(20) "Hello world, guest!
    "