how to get output of proc_open()
Your code more or less works for me. time
prints its output to stderr
so if you're looking for that output, look in your file files/temp/error-output.txt
. The stdout
pipe $pipes[1]
will only contain the output of the program ./a
.
My repro:
[edan@edan tmp]$ cat proc.php
<?php
$cwd='/tmp';
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("file", "/tmp/error-output.txt", "a") );
$process = proc_open("time ./a a.out", $descriptorspec, $pipes, $cwd);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
?>
[edan@edan tmp]$ php proc.php
a.out here.
[edan@edan tmp]$ cat /tmp/error-output.txt
real 0m0.001s
user 0m0.000s
sys 0m0.002s
PHP Use proc_open and capture stdout of 'echo' command
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!
"
output problems with proc_open()
When using the CLI version of PHP, the output is still buffered - so the usual time that a page is sent to the user is at the end of the script.
As with any version of PHP - using flush()
will force the output to be sent to the user.
Also - you should use PHP_EOL
, it outputs the correct new lines for whatever platform your on (linux and Windows use different chars - \r\n or \n). PHP_EOL
is a safe way of creating a new line.
Is there a way to make proc_open read input from a file if the file is dynamic?
Wait for the file to be created before using it.
while !file_exists("input.txt") {
sleep(5)
// code that uses input.txt
}
...
unlink("input.txt") # Remove file to prepare for next iteration
To avoid seeing a partial file, the process that creates the file should write to a temporary name, then rename it to input.txt
when it's done.
Redirect pipe acquired by proc_open() to file for remainder of process duration
What I ended up doing, having reached the point where the service had been initialized correctly, was to redirect the pipes from the already opened process as the standard input to a cat
process per-pipe, also opened by proc_open()
(helped by this answer).
This wasn't the whole story, as I got to this point and realised that the async process was hanging after a while due to the stream buffer filling up.
The key part that I needed (having set the streams to non-blocking previously) was to revert the streams to blocking mode, so that the buffer would drain into the receiving cat
processes correctly.
To complete the code from my question:
// Iterate over the streams that are stil open
foreach(array_reverse($readables) as $stream) {
// Revert the blocking mode
stream_set_blocking($stream, true);
$cmd = 'cat';
// Receive input from an output stream for the previous process,
// Send output into the internal unified output buffer
$pipes = [
0 => $stream,
1 => $this->temp,
2 => array("file", "/dev/null", 'w'),
];
// Launch the process
$this->cats[] = proc_open($cmd, $pipes, $outputPipes = []);
}
Related Topics
Laravel: Validation Unique on Update
Checking If All the Array Items Are Empty PHP
Not Equal to != and !== in PHP
Laravel - Pass More Than One Variable to View
Check Whether or Not a Cidr Subnet Contains an Ip Address
Tell Bots Apart from Human Visitors for Stats
Woocommerce: Add Product to Cart with Price Override
Can't Install Laravel Installer via Composer
How to Create a Random String Using PHP
PHP MySQL Search Multiple Tables Using a Keyword
Crop Whitespace from Image in PHP
Uploading File in PHP Server from Android Device
Increment Value in MySQL Update Query
Get Variable from PHP to JavaScript