Ok before the flaming starts I did some research here and at some other links:
Run process with realtime output in PHP
This is what I am currently using:
<?php
$descriptorspec = array(
0 => array("pipe", "r"), // stdin
1 => array("pipe", "w"), // stdout
2 => array("pipe", "w"), // stderr
);
flush(); ?>
<?php $process = proc_open($_POST['field1'], $descriptorspec, $pipes, dirname(__FILE__), null);?>
<?php $stdout = stream_get_contents($pipes[1]); fclose($pipes[1]); $stderr = stream_get_contents($pipes[2]); fclose($pipes[2]); ?>
This works fantastic for outputting any stdout and stderr from a console application to my webpage, however, due to what I am assuming is buffering it does not update in realtime. I have tried the methods in the link I posted and a similar method in Ajax but neither would update in realtime, just wait for all of the input to finish then display on the page.
All I can come up with is that php is waiting for the proc_open() command to finish executing before it tries to do anything with the output.
Any insight would be much appreciated.
Thanks!
Related
I am trying to create a C program compiler + executer using PHP.
My PHP code is
<?php
$cwd='/path/to/pwd';
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("file", "/path/to/log/file", "a") );
$process = proc_open("./a.out", $descriptorspec, $pipes, $cwd);
fwrite($pipes[0], 123);
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
My C file is
#include <stdio.h>
int main() {
int a;
printf("Enter a number");
scanf("%d", &a);
printf("The value is: %d", a);
return 0;
}
Now when I run this, I am getting the output
Enter a numberThe value is: 123
Is there anyway to do it like a terminal execution? So it should wait for the input after showing Enter a number. Then once I enter the number it will execute further and show the output.
It will be like a web site with a terminal.
Will it be possible with proc_open and PHP? Is it possible to achieve by using Web socket in some way?
Please help. Thanks in advance.
I use the following code to open a process with proc_open, and to save the handle and the pipes to a file:
$command = "COMMAND_TO_EXECUTE";
$descriptors = 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("file", "error-output.txt", "a") // stderr is a file to write to
);
$pipes = array();
$processHandle = proc_open($command, $descriptors, $pipes);
if (is_resource($processHandle)) {
$processToSave = array(
"process" => $processHandle,
"pipes" => $pipes
);
file_put_contents("myfile.bin", serialize($processToSave) );
}
And in a second moment i need to retrieve this file handle from the file, i've used this code:
$processArray = unserialize(file_get_contents("myfile.bin"));
$processHandle = $processArray["process"];
$pipes = $processArray["pipes"];
But when I print a var_dump of $processHandle and $pipes after retrieving from file, I'll get integers instead of resource or process, but why??
var_dump($processHandle) -> int(0)
var_dump($pipes) - > array(2) { int(0), int(0) }
And at this point of course, if I try to close the pipes, i will get an error, resource expected, integer given.
How can I make this working? (NOTE: This is the solution I'm looking for)
But alternatively, I can get also the pid of process and then use this pid to stop or kill or do anything else with the process, but what about the pipes?
How can I read/write or save error from/to the process?
Thank you
Found the solution to myself, it's not to possible to serialize resource and when the script has done, those resource handler were free.
Solution was to create a daemon listening on a port, wich on request launch and stop process. Because the process is always running, it can maintain a list of handler process and stop when requested.
I'm trying to spawn a process using following statement
$cmd = "Hello.scala";
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w")
);
$process = proc_open($cmd, $descriptorspec, $pipes, $cwd, null);
through PHP script. I'm using spawned process to execute a simple Scala program and capturing program's output. But unfortunately I'm not getting success. Child process runs successfully but after few seconds its getting terminated due to sigterm signal.
$stat = proc_get_status($process);
if ($stat['signaled'] && $stat['termsig'] == 9){
echo "Process got sigterm";
}
finally its printing Process got sigterm. I tried all the way to increase CPU time using ulimit in httpd and I also tried to set max execution time but no success. I will really appreciate any help on this.
For some strange reason this
echo system("echo 'echo hello > /dev/pts/2' | /usr/bin/at 19:36");
Refuses to work from my php script, however the command works fine when I just enter it through command line.
I know php has permission to execute some commands. I can run 'ls' from the php script but not the 'at' command. I've tried playing around with file permissions, but so far to no avail :(
edit
Permissions for /usr/bin/at are:
-rwxr-sr-x 1 daemon daemon 42752 Jan 15 2011 at
I think it's a permissions problem, if I execute the php file from my ssh terminal it works fine, but not from the web.
What you are executing is
echo 'hello' > /dev/pts/2 | /usr/bin/at 19:36
meaning
echo 'hello' > /dev/pts/2
and pipe stdout to /usr/bin/at 19:36 but since you already redirected the echo to /dev/pts/2, this will be empty. What you probably meant to do is:
echo system("echo 'echo hello > /dev/pts/2' | /usr/bin/at 19:36");
You might also want to use shell_exec to pass the command through a shell or alternatively proc_open which gives you better control over stdin/out/err of the command you are executing. Your example would correspond to (adapted example from php.net docs):
<?php
$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('/usr/bin/at', $descriptorspec, $pipes);
if (is_resource($process)) {
fwrite($pipes[0], 'echo "hello" > /dev/pts/2');
fclose($pipes[0]);
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
$return_value = proc_close($process);
echo "command returned $return_value. stdout: $stdout, stderr: $stderr\n";
} else {
echo "Process failed";
}
?>
In your php.ini file check for disable_functions sometimes functions like system are disabled for security reasons.
I'm trying to get
`mysql -uroot`;
to enter the MySQL interactive client just as executing
$ mysql -uroot
from the shell does.
It's okay if the PHP script exists after (or before), but I need it to invoke the MySQL client.
I've tried using proc_open() and of course system(), exec() and passthru(). Wondering if anyone has any tips.
New solution:
<?php
$descriptorspec = array(
0 => STDIN,
1 => STDOUT,
2 => STDERR
);
$process = proc_open('mysql -uroot', $descriptorspec, $pipes);
Old one:
Save for tab completion (you could probably get it in there if you read out bytes with fread instead of using fgets), this gets you on your way, lots left to tweak:
<?php
$descriptorspec = array(
0 => array("pty"),
1 => array("pty"),
2 => array("pty")
);
$process = proc_open('mysql -uroot', $descriptorspec, $pipes);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking(STDIN,0);
do {
echo stream_get_contents($pipes[1]);
echo stream_get_contents($pipes[2]);
while($in = fgets(STDIN)) fwrite($pipes[0],$in);
} while (1);
I guess it does work, but it's waiting for some input. Try sending some sql commands to it's stdin. Of course, since the backtick operator doesn't support IO remapping, you'll need more complex process handling.