I have a php script that runs a python script. I have to compare python script's output with specific constants in php script.
I tried using exec and popen. Here is the code I tried so far
$out=NULL;
$pid=exec("python /home/krishna/online/createProblems.py $contest $pcode $fn1 $fn2",$out) or die("error");
if ($out=="1"){echo "Successfully inserted problem";}
and using popen
$pid=popen("python /home/krishna/online/createProblems.py $contest $pcode $fn1 $fn2","r") or die("error");
$ot=fread($pid,256);
if ($ot=="1"){echo "Successfully inserted problem";}
Both codes are not working properly....
When I tested outputs I got "1" as output. but comparing with "1" is not working.
You can use pipes for stdin, stdout and stderr.
function get_output($cmd) {
$descriptorspec = array(0 => array('pipe', 'r'), // stdin
1 => array('pipe', 'w'), // stdout
2 => array('pipe', 'w')); // stderr
$process = proc_open($cmd, $descriptorspec, $pipes);
$output = '';
if (is_resource($process)) {
fwrite($pipes[0], 'some std input can be here'); // not necessary
fclose($pipes[0]);
$output = stream_get_contents($pipes[1]);
$err = stream_get_contents($pipes[2]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
if (!empty($err)) {
throw new Exception();
}
}
return $output;
}
Now you should pass the needed $cmd to be executed.
Related
I have a command line program which requires for the user to type a password in order to run. I want to run it and enter the password through a php script.
I have tried using proc_open, using the following code, but it does not work. It reads the input, but fwrite does not seem to do anything.
$cmd = "cmd /c command_line_program";
$descriptorspec = array(
0 => array('pipe', 'r'), //STDIN
1 => array('pipe', 'w'), //STDOUT
2 => array('pipe', 'r'), //STDERR
);
$process = proc_open(
$cmd,
$descriptorspec, $pipes, null, null);
if (is_resource($process)) {
$buffer = "";
// Read from the command's STDOUT until it's closed.
while (!feof($pipes[1])) {
$input = fread($pipes[1], 8192);
$buffer .= $input;
if (strpos($buffer, 'Password:') !== false){
fwrite($pipes[0], "userpass\n");
}
}
proc_close($process);
} else {
echo 'Not a resource';
}
What am I doing wrong? Is there some other solution except proc_open? I am using windows and php 7.2.
According to PHP proc-open.php documentation and the comments bellow are recommendation to:
close all three streams (store the return value issue):
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
Assign the return value to a variable ( passing passwords to the process)
$exit_status = proc_close($process);
Both are missing in your code.
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 want to run .exe file from php. It asks for user input one by one. Is there any way I can do this.
I tried using shell_exec(), exec() but they didn't return the expected results.
I found a solution for my own query, please find the piece of code below that solved the purpose:
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("file", "error.txt", "a")
);
$process = proc_open('xyz.exe', $descriptorspec, $pipes);
$input1 = "1";
if (is_resource($process)) {
print fgets($pipes[1]); // this will help you read the lines
fwrite($pipes[0], $input1."\n"); // to provide input
print fgets($pipes[1]);
fclose($pipes[1]);
fclose($pipes[0]);
$return_value = proc_close($process);
echo "command returned $return_value\n";
} else {
echo "Resource unavailable";
}
I have a program that reads a JSON request from stdin, which I want to call in PHP.
Here's what I have right now
<?php
echo exec(
'echo \''.json_encode($_POST,JSON_NUMERIC_CHECK).'\' | '.
'program'
);
?>
This works, but is there a more direct way to put a string in PHP in stdin?
Something along the lines of pipe(json_encode($_POST,JSON_NUMERIC_CHECK),'program') maybe?
What I have may be fine in this particular case, but what if instead of JSON, I'll need to pipe binary data? What if it's too long to fit into a shell argument, or contains single quotes?
Edit:
Following miken32's suggestion, I used proc_open() like this:
$proc = proc_open(
'LD_LIBRARY_PATH=/foo/bar/lib program args',
array(0 => array('pipe','r'), 1 => array('pipe','w')),
$pipes,
NULL
//, array('LD_LIBRARY_PATH','/foo/bar/lib')
);
if (is_resource($proc)) {
fwrite($pipes[0],json_encode($_POST,JSON_NUMERIC_CHECK));
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
proc_close($proc);
}
?>
But I had to add LD_LIBRARY_PATH=/foo/bar/lib to the command argument. The $env argument seems to have no effect. Does anyone know why?
You can use popen() to create a pipeline to a process:
<?php
$data = json_encode($_POST, JSON_NUMERIC_CHECK);
$p = popen("program", "w");
fwrite($p, $data . PHP_EOL);
$exit_code = pclose($p);
If you need to get data back from the program, things get more involved and you need to use proc_open() instead.
<?php
$data = json_encode($_POST, JSON_NUMERIC_CHECK);
$fds = [
0=>["pipe", "r"], // STDIN
1=>["pipe", "w"], // STDOUT
2=>["pipe", "w"], // STDERR
];
$dir = "/path/to/working/directory";
$env = [
"PATH" => "/usr/local/foo/bin:/usr/local/bin:/usr/bin",
"LD_LIBRARY_PATH" => "/usr/local/foo/lib/",
];
$p = proc_open("program", $fds, $pipes, $dir, $env);
fwrite($pipes[0], $data . PHP_EOL);
fclose($pipes[0]);
$return = stream_get_contents($pipes[1]);
$err = stream_get_contents($pipes[2]);
fclose($pipes[1]);
fclose($pipes[2]);
$exit_code = proc_close($p);
if ($exit_code == 0) {
// successful return
echo $return;
} else {
// error
echo "ERR: $err";
}
Hi all I have a c compiler up and running shows the output but the problem is that it dosen't show errors....
shell_exec("gcc xyz.c -o ab.out ");
$output=exec("./ab.out");
echo $output;
So it is showing output but not any errors occurred while compiling.
Any help is duly appreciated.
Thanks in advance.
Any error output from the command you run will go to STDERR and none of the exec, shell_exec functions will provide you that. One way is to redirect it
exec("gcc test.c 2>&1", $out);
The most cleaner way is to use proc_open function.
$descriptorspec = array(
1 => array("pipe", "w"), // stdout
2 => array("pipe", "w") // stderr
);
$process = proc_open('gcc test.c', $descriptorspec, $pipes);
if (is_resource($process)) {
$stderr = stream_get_contents($pipes[2]);
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
fclose($pipes[2]);
$return_value = proc_close($process);
}