PHP Powershell command - php

Trying to run the following command in php to run powershell command...
the following works:
$output = shell_exec(escapeshellcmd('powershell get-service | group-object'));
I can not run it like this:
$output = shell_exec('powershell get-service | group-object');
it will not pass the pipe | character
but if I try to run:
$output = shell_exec(escapeshellcmd('powershell get-service | where-object {$_.status -eq "Running"}'));
I get no output.
The following:
$cmd = escapeshellcmd('powershell get-service | where-object {$_.status -eq "Running"}');
returns:
powershell get-service ^| where-object ^{^$_.status -eq ^"Running^"^}
Any suggestions on why this is happening and how to fix this?
Edit: Also I could run it as .ps1 script but I want to be able to pass $var to it.

I'll take a stab although I have no PHP experience whatsoever.
I have a feeling that what's happening is your pipe character is being interpreted by the command shell instead of PowerShell. For example if you ran the following at the cmd.exe command prompt:
dir /s | more
The output of the first command gets piped to the input of the second just like you'd expect in PowerShell.
Escaping the string will only make the problem worse because you're transforming the string in such a way that PowerShell has no idea how to unescape it.
Try enclosing your original PowerShell expression in a quote like the following:
$output = shell_exec('powershell.exe -c "get-service | group-object"');
Or preferably, it looks like there's an exec() function that does not go through the command shell. This might work better.
$output = exec('powershell.exe -c get-service | group-object');

'powershell get-service | group-object'
will be interpreted as
run powershell and pass it get-service as an argument
then pipe the output of powershell to group_object (i.e. not the output of get-service)
What you want is for powershell to see get-service | group-object as it's argument, so you have to enclose that in quotes, like this.
$output = shell_exec('powershell "get-service | group-object"');

Related

using shell_exec with a command with a pipe ( | )

Hi i have a Linux command what uses a pipe to obtain its result. It basically search a pdf for a string and returns the page numbers of all of the occurrences.
pdftotext /var/www/html/custom/test.pdf - | awk -vRS=$'\\f' -vNAME='06/1133/13' \ 'index($0,NAME){printf \"%d,\", NR}'
The result of this on the command line looks like this:
8,9,10,11,
Trying to run this in php with this code
$command = "pdftotext /var/www/html/custom/test.pdf - | awk -vRS=$'\\f' -vNAME='06/1133/13' \ 'index($0,NAME){printf \"%d,\", NR}'";
echo shell_exec($command);
i get the following output
1,
I have used the php script to print out the command variable to make sure the formatting is correct. I can run the output command on the terminal and this works with out issue.
What is needed within the PHP script to allow this to run?

Why do some of my shell_exec's sometimes fail with a Broken pipe, while still producing the necessary output?

I wrote a very convoluted, very hackjob PHP-cli script that receives and parses JSON of changeable structure, depth and content. For that reason at that time I found it easiest to do the parsing using PHP's shell_exec() and cat | jq | grep.
Sometimes, rarely, on certain input it gives me the message Error: writing output failed: Broken pipe, which is the last message I see in cli output before the script dies. However, even when it does do that, the data is still parsed out correctly, for all the little good it does me.
I isolated the problematic piece of code to:
$jq1='cat '.$randfile.' | jq \'.\' | grep "\[" -m 1 | grep -Po --color=none "\w{3,15}"';
$jq1=trim(shell_exec($jq1));
And tried to debug it by seeing what it executes. The first line is the shell_exec argument, echoed before execution, the second line is the result of shell_exec.
Command: cat 5ca15f21.json | jq '.' | grep "\[" -m 1 | grep -Po --color=none "\w{3,15}";
Result: standalone
Command: cat 5ca59379.json | jq '.' | grep "\[" -m 1 | grep -Po --color=none "\w{3,15}";
Result: season
Error: writing output failed: Broken pipe
Command: cat 5ca7d271.json | jq '.' | grep "\[" -m 1 | grep -Po --color=none "\w{3,15}";
Result: extended
Command: cat 5ca7d7a8.json | jq '.' | grep "\[" -m 1 | grep -Po --color=none "\w{3,15}";
Result: season
(I have seen the error of my lazy ways and will be rewriting that whole section, but back then I was young and inexperienced and impatient. I'd still like to understand what's going wrong where why.)
What would make it do that sometimes? The input is always jq's pretty-printed JSON, of varying structure.
Even if it does get the broken pipe message, the necessary value is still parsed out and stored in the variable. What causes it to die then? I would like to know for the future if there's a way to make PHP disregard the [non-fatal] error and go on executing.
Why does the shell command that produces the broken pipe error message in shell_exec behave no differently when invoked manually in bash? Where is the broken pipe and what makes it so broken?
Edit:
The cat command could be eliminated if this is a bash command to be executed. I would write it like this.
$jq1=grep -Po --color=none "\w{3,15}"|"\[" -m 1 file.txt | jq \'.\';
$jq1=trim(shell_exec($jq1));
I combined your redundant grep commands and added file to the grep command and only piped the jq command.

PHP calling diff with two strings

I'm able to call diff via exec() just fine with files, like so:
exec('diff -N -u '.escapeshellarg($oldfile).' '.escapeshellarg($newfile), $lines);
However, attempting to do this with arbitrary strings fails:
exec('diff -N -u <(echo '.escapeshellarg($oldstring).') <(echo '.escapeshellarg($newstring).')', $lines);
If I copy the command being run into bash, it works just fine. But when run in PHP I get no output. Even 2>&1 doesn't yield anything. Capturing the status code yields 1, which should indicate that diff found differences, but I still get 1 even in the case where $newstring === $oldstring.
So I'm not quite sure what's going on. I can only assume that, for some reason, exec doesn't like process substitutions? Any ideas?
PHP's exec runs the command with /bin/sh, which does not support process substitution (even when sh is provided by bash).
You can instead run your command explicitly with bash -c.
Sadly, PHP has no convenience functions for safe and robust execv style execution, so the easiest way to do that to build your diff command and then escape the whole thing:
exec('bash -c ' . escapeshellarg('diff -N -u <(echo '.escapeshellarg($oldstring).') <(echo '.escapeshellarg($newstring).')'), $lines);
What shell is being used? Make sure diff is in the $PATH, otherwise command will fail.

exec issue with netstat and lsof

I want to check if a certain tunnel exists from inside PHP using (any of these commands):
$(which lsof) -i -n | grep ssh
$(which netstat) -a | grep "localhost:ssh"
The issue is that when I run the commands in the shell everything is fine but from php running them like:
$reply = exec(CMD);
always return nothing.
Any ideas?
Thank you!
You could redirect stderr to stdout and get the $output and $return_var. To do that, change your exec() call like this:
exec('$(which lsof) -i -n | grep ssh 2>&1', $output, $return_var);
var_dump($return_var);
var_dump($output);
More info about exec here: http://php.net/manual/en/function.exec.php (have a look at $output and $return_var parameters).
I think the issue is more to do with how PHP interprets your command...
In this case (assuming instead of CMD you write same command you try in shell), it would try to:
$reply = exec($(which lsof) -i -n | grep ssh);
means it would try to substitute the bold part as a PHP variable, and try to execute the resultant string. As the output of "-i -n |grep ssh" is null, so you get nothing as a result.
I would suggest you to instead:
$lsof = exec(which lsof);
$reply = exec($lsof -i -n | grep ssh);

php shell_exec echo

I'm working on interfacing a microcontroller with a lamp server. I am trying to run the command echo -e -n "data \r" > /dev/ttyUSB0 using shell_exec in php but with no results. It works just fine from the command line. Doing a little experimenting, I discovered that echo -e -n "1 \r" actually echoes -e -n 1. Is there a reason it won't take the -e or -n options?
Here's my code:
<?php
shell_exec('echo -e -n "1 \r" > /dev/ttyUSB0');
?>
Instead of using shell_exec and echo, why not use PHP's filesystem functions?
file_put_contents('/dev/ttyUSB0', "1 \r");
There are some other functions too, try this function maybe you get your answer.
exec(command, $output);
This function takes a command and assigns to $output an array where each element is a line of the generated output.
I ran into similar problem, calling from php
php > echo shell_exec("echo -e aaa\tbbb");
-e aaa bbb
note, that output contains "-e", while I have expected that 'echo' command will interpret -e as flag and would not send it to output.
After doing some investigation I came to following conclusion:
when exec or shell_exec are called from php - new shell interpreter is launched.
php launches "sh".
When I was running on CentOS sh was a symlink to bash, and exec("echo ...") worked as I would have expected.
Now I am running Ubuntu. sh is a symlink to dash, not bash!
And final root cause - builtin echo command in dash does not have/understand '-e' flag, so it just forwards it to output
This is an old question but it goes what worked for me in case someone else comes across with this as well.
Yesterday night I've messing around and struggling with this myself. For this to work, the command you need to use should start by calling the echo bin directly /bin/echo... instead of only echo.
Also don't forget to use single quote /bin/echo... instead of double quote to avoid PHP null byte detection error (this part you did correctly).
I had a similar problem running with -e, I was trying to change the password from a php
running this didnt work
exec("echo -e \"$pass\\n$pass\" | passwd $user");
It said passwords dont match. Checking the echo i saw that -e was includes as a part of the echoing so i changed it to
exec("echo \"$pass\\n$pass\" | passwd $user");
And then it worked.

Categories