I have a problem passing environment variables to processes that i opened with proc_open.
I found the following example on http://us2.php.net/manual/en/function.proc-open.php
<?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("file", "/tmp/error-output.txt", "a") // stderr is a file to write to
);
$cwd = '/tmp';
$env = array('some_option' => 'aeiou');
$process = proc_open('php', $descriptorspec, $pipes, $cwd, $env);
if (is_resource($process)) {
// $pipes now looks like this:
// 0 => writeable handle connected to child stdin
// 1 => readable handle connected to child stdout
// Any error output will be appended to /tmp/error-output.txt
fwrite($pipes[0], '<?php print_r($_ENV); ?>');
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
// It is important that you close any pipes before calling
// proc_close in order to avoid a deadlock
$return_value = proc_close($process);
echo "command returned $return_value\n";
}
?>
The example should echo the env array like the documentation say. But on my machine (PHP 5.4.6-1ubuntu1.4 (cli)) the echoed array is empty. Are there some Suhosin or php.ini restrictions that ban env var passing to processes? I have no idea.
If $_ENV is empty, you should have a look at your variables_order ini setting and ensure that the value contains the E
However, you can use $_SERVER instead:
fwrite($pipes[0], '<?php print_r($_SERVER); ?>');
It will contain environment variables too and should be enabled at 99.999% of servers (I guess)
Set
variables_order = "EGPCS"
in your php.ini
Related
I'am stuck since days while requesting grep on PHP, it work in cli but don't return anything via http.
it search for files that contain non UTF-8 carachters
in CLI it retrun ������ but nothing (array is null) from the web
<?php
exec("/sbin/grep -axv '.*' /srv/http/test 2>&1", $datareturn);
print_r($datareturn);
?>
disable_functions = is empty in php.ini
Also tried with proc_open :
<?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("file", "/tmp/error-output.txt", "a") // stderr is a file to write to
);
$process = proc_open(
"/sbin/grep -axv '.*' /srv/http/test",
$descriptorspec,
$pipes
);
if (is_resource($process)) {
// Closing $pipes[0] because we don't need it
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
//avoid a deadlock
$return_value = proc_close($process);
echo "command returned $return_value\n";
}
?>
In CLI it return :
"������
command returned 0
From http, "command returned 1", error-output.txt is empty in 2 cases
I've been trying to figure out why I can't get NMap to give me any sort of output nor even work for that matter via PHP.
Things I've tried so far:
// this doesn't return anything because it's wrong
$output = passthru('nmap -V');
echo $output;
// this returns a negated integer value
passthru('nmap -V', $output);
echo $output;
// this doesn't return anything either
$stream = popen('C:\nmap -V', 'r');
while (!feof($stream))
{
$buffer = fread($stream, 1024);
echo $buffer;
}
pclose($stream);
// this doesn't do anything as well
$output = system('C:\nmap -V');
echo $output;
// this does nothing also...
ob_start(); // start output buffering
fpassthru('C:\nmap -V'); // flush COMPLETE output of nmap
$output = ob_get_contents(); // capture output buffer contents
ob_end_clean(); // shutdown output buffers
echo $output; // echo it
.
// okay, how about we try a 'proc_open()'?
// nope, this doesn't work either. I just get a value of "command returned -1073741515"
$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("file", "errors/errors.txt", "a") // stderr is a file to write to
);
$cwd = 'errors';
$env = array('some_option' => 'aeiou');
$process = proc_open('C:/nmap -V', $descriptorspec, $pipes, $cwd, $env);
if (is_resource($process))
{
// $pipes now looks like this:
// 0 => writeable handle connected to child stdin
// 1 => readable handle connected to child stdout
// Any error output will be appended to /errors/errors.txt
fwrite($pipes[0], '<?php print_r($_ENV); ?>');
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
// It is important that you close any pipes before calling
// proc_close in order to avoid a deadlock
$return_value = proc_close($process);
echo "command returned $return_value\n";
}
And many others, but I get absolutely NOTHING back from $output. I've done a lot of Google searching too, but I still can't figure it out. Many examples also seem to be for Linux which doesn't help.
Thanks.
Okay, I get an output using this code. I will continue coding and finish the rest of the program. Thanks to 'Chris Haas' for the suggestion in using proc_open
NOTE: The directory that contains the 'errors.txt' file must have 'IIS_IUSRS' write permissions. When in doubt, check your PHP error log.
$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("file", "errors/errors.txt", "a") // stderr is a file to write to
);
$env = array('bypass_shell' => true);
$process = proc_open("NMAP.EXE -V", $descriptorSpec, $pipes, "C:\\Program Files (x86)\\NMap", $env);
if (is_resource($process))
{
// '$pipes' now looks like this:
// 0 => writeable handle connected to child stdin
// 1 => readable handle connected to child stdout
fwrite($pipes[0], '<?php print_r($_ENV); ?>');
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
// it is important that you close any pipes before calling
// proc_close in order to avoid a deadlock
$return_value = proc_close($process);
echo "<br /><br />Command Returned: $return_value\n";
}
Nmap version 7.91 ( https://nmap.org ) Platform:
i686-pc-windows-windows Compiled with: nmap-liblua-5.3.5
openssl-1.1.1h nmap-libssh2-1.9.0 nmap-libz-1.2.11 nmap-libpcre-7.6
Npcap-1.00 nmap-libdnet-1.12 ipv6 Compiled without: Available nsock
engines: iocp poll select
Command Returned: 0
I'm using Stanford namespace But having this warning in Stanford Tagger.php
Warning: proc_open(): CreateProcess failed, error code - 0
it's caused by this line
$process = proc_open($cmd, $descriptorspec, $pipes, dirname($this->getJar()));
I can't know how to resolve it.
I had a look at the example in the php documentation and I was getting the exact same error as well (I am on windows using WAMP).
After some digging around, I found that I can fix the problem by omitting out the dir and env params, for example - this works for me:
<?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("file", "error-output.txt", "a") // stderr is a file to write to
);
$cwd = 'D:/wamp/www/test';
$env = array('some_option' => 'aeiou');
$process = proc_open('php', $descriptorspec, $pipes, /* $cwd, $env */ );
if (is_resource($process)) {
// $pipes now looks like this:
// 0 => writeable handle connected to child stdin
// 1 => readable handle connected to child stdout
// Any error output will be appended to /tmp/error-output.txt
fwrite($pipes[0], '<?php print_r($_ENV); ?>');
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
// It is important that you close any pipes before calling
// proc_close in order to avoid a deadlock
$return_value = proc_close($process);
echo "command returned $return_value\n";
}
?>
So, can you try updating your code from:
$process = proc_open($cmd, $descriptorspec, $pipes, dirname($this->getJar()));
To:
$process = proc_open($cmd, $descriptorspec, $pipes);
If this works for you, then the problem is with this line dirname($this->getJar()) of your code. Either this path does not exists or the it's not accessible.
Have you do a var_dump() of dirname($this->getJar()) and check if that path exists?
The above example was fixed by setting current working dir like this also:
$process = proc_open('php', $descriptorspec, $pipes, getcwd(), $env );
According to documentation:
cwd
The initial working dir for the command. This must be an absolute directory path, or
NULL if you want to use the default value (the working dir of the current PHP process)
My PHP web app receives data from a stream. Once the page is loaded I need to open an .exe file using system() or exec() and after short period of time new data will come, so I must type specific command to this .exe to get its returned value, how can I do this?
I'm only able to do this manually in command prompt
path/to/.exe :: hit 'Enter'
command1 params1
//...
What you're looking for is proc_open(). http://php.net/manual/en/function.proc-open.php
This will allow you to work with STDIO streams to communicate with the separate process.
Example from the PHP documentation:
$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("file", "/tmp/error-output.txt", "a") // stderr is a file to write to
);
$cwd = '/tmp';
$env = array('some_option' => 'aeiou');
$process = proc_open('php', $descriptorspec, $pipes, $cwd, $env);
if (is_resource($process)) {
// $pipes now looks like this:
// 0 => writeable handle connected to child stdin
// 1 => readable handle connected to child stdout
// Any error output will be appended to /tmp/error-output.txt
fwrite($pipes[0], '<?php print_r($_ENV); ?>');
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
// It is important that you close any pipes before calling
// proc_close in order to avoid a deadlock
$return_value = proc_close($process);
echo "command returned $return_value\n";
}
You could also consider shared memory if you need more than one listener, but this scenario sounds like you would benefit from using a queue.
Documentation msg_get_queue, msg_receive, msg_send
Example
// Send
if (msg_queue_exists(12345)) {
$mqh = msg_get_queue(12345);
$result = msg_send($mqh , 1, 'data', true);
}
// Receive
$mqh = msg_get_queue(12345, 0666);
$mqst = msg_stat_queue($mqh);
while ($mqst['msg_qnum']) {
msg_receive($mqh, 0, $msgtype, 2048, $data, true);
// Spawn your process
$mqst = msg_stat_queue($mqh);
}
Edit
Semaphore functions aren't available on Windows, as suggested above your best bet is to go with popen (unidirectional) or proc_open for bi-directional support.
I'm invoking the proc_open() and I can't capture the output of the process written to the stderr:
$curFolder = getcwd();
$procDescriptor = array( 2 => array( "pipe", "w" ) );
$cmd = "MyApp.exe -f optimization.csv";
$process = proc_open( $cmd, $procDescriptor, $pipes, $curFolder );
if( is_resource( $process ) == true )
{
$procStatus = proc_get_status( $process );
while( $procStatus['running'] === true )
{
if( !feof( $pipes[2] ) )
{
$logLine = fgets( $pipes[2] );
echo( "Read >${logLine}<" );
}
sleep( 1 );
}
}
The program hangs on the fgets(). If I run the program from the command line, everything works, i.e. there is something written to the stderr (and I also tried by using the stdout with the same result). I'm running the script on Windows - the same script on Linux runs smoothly.
You have an endless loop.
$procStatus['running'] will never change unless you put the call to proc_get_status() inside the loop. PHP does not have dynamic properties like JavaScript.
I added the line
$procStatus = proc_get_status( $process );
right after the sleep() and it works fine.
From the proc_open() 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("file", "/tmp/error-output.txt", "a") // stderr is a file to write to
);
$cwd = '/tmp';
$env = array('some_option' => 'aeiou');
$process = proc_open('php', $descriptorspec, $pipes, $cwd, $env);
if (is_resource($process)) {
// $pipes now looks like this:
// 0 => writeable handle connected to child stdin
// 1 => readable handle connected to child stdout
// Any error output will be appended to /tmp/error-output.txt
fwrite($pipes[0], '<?php print_r($_ENV); ?>');
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
// It is important that you close any pipes before calling
// proc_close in order to avoid a deadlock
$return_value = proc_close($process);
echo "command returned $return_value\n";
}
?>
Perhaps your process doesn't report to stderr if you find it empty
I'd recommend also adding stdin and stdout streams, even if you don't consume the data; some C libraries get into a tizzy if the streams are not there, and can either exit early (glibc) or potentially wedge (some versions of MS libc).