GetOpt doesn't read full URL - php

I have a script that need to run from a terminal or a command prompt. I'm using PHP. GetOpt is the function that I use to get data or a parameter that the user input in the terminal.
This is my script.
<?php
$opt = getopt("f:");
$input = $opt['f'];
$u = fopen($input, 'r');
echo "\n\n$input\n\n";
I tried to run it like this:
$ php myscript.php -f http://myurl.com/file.csv?city=london&status=3
My url is http://myurl.com/file.csv?city=london&status=3, but it only outputs http://myurl.com/file.csv?city=london. The status parameter is lost from the full URL.
How can I get this to work?

it's because you have to wrap your link around into quotes:
$ php myscript.php -f "http://myurl.com/file.csv?city=london&status=3"
I'll go ahead and assume you are running your script in Bash, and & in Bash might be interpreted as bitwise AND in your case:
$ echo $(( 98 & 7 ))
2

Related

Unable to call a python script through PHP

I Have been stuck for a couple of days now. I am attempting to call a simple python script from PHP. For the life of me I cannot figure out what the issue is. I have made the onoff.py script executable with chmod +x.
I can run the script just fine from the command line like this:
pi#raspberrypi:/var/www/html $ python onoff.py
LED on
LED off
My issue is when I try to call the script from PHP. I get nothing.
My Python Script:
#!/usr/bin/python
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(18,GPIO.OUT)
print "LED on"
GPIO.output(18,GPIO.HIGH)
time.sleep(1)
print "LED off"
GPIO.output(18,GPIO.LOW)
My PHP Script:
<?php
$command = escapeshellcmd('python /var/www/html/onoff.py');
$output = shell_exec($command);
echo $output;
?>
Any help is greatly appreciated!
EDIT:
if I change my onoff.py script to a simple while loop such as:
#!/usr/bin/python
x=1
while (x<10):
print x
x=x+1
the output on the browser is:
1 2 3 4 5 6 7 8 9
I just don't understand why the loop will run but I get no output with the original python code.
EDIT 2:
Ok So I taking a different approach and trying to see where the code fails. I am adding bits of code at a time. Please see the following.
#!/usr/bin/python
import random
import time
import RPi.GPIO as GPIO
randomNumber = random.randint(1, 20)
GPIO.setmode(GPIO.BCM)
#GPIO.setup(18,GPIO.OUT)
print randomNumber
Now when I run the PHP it shows a random number so I know the python script is running. When I un-comment GPIO.setup(18,GPIO.OUT) and run the php I get a blank screen. I have no idea why this would make the script fail.
shell_exec() will only return a string if $command a). Ran OK and assuming b). that it spits its response to STDOUT.
Use exec() and pass it your command, an integer $code and an empty array $response both of which are treated by PHP as arguments by reference.
Run your command thus:
$command = escapeshellcmd('/path/to/python /var/www/html/onoff.py');
$response = array();
$code = 0;
exec($command, $response, $code);
var_dump($code, $response);
die;
You should now see what is actually being given to PHP internally and why the Python script isn't working.
You need to use python before the script, i.e.:
$command = escapeshellcmd('python /var/www/html/onoff.py');
If it doesn't work, python probably ins't on the PATH of the apache user and you may need to use the full path to the python binary, use which to find the full path:
which python
//usr/bin/python
The use that value:
$command = escapeshellcmd('/usr/bin/python /var/www/html/onoff.py');
Note:
Make sure apache user has execute permissions on onoff.py

Passing arguments from PHP to a remote shell script

I am executing a shell script located on a remote machine from a PHP script. So, let's say that PHP script runs on A and shell script runs on B (10.0.0.37).
I have the following code which runs well
$cmd = "ssh 10.0.0.37 /usr/tmp/script.sh";
exec($cmd, $output);
Now, I want to pass arguments to the shell script, preferably in JSON format.
The output of echo json_encode($arg) is as follows:
[{"original_name":"pdf_convert","changed_name":"pdf_convert_1"},{"original_name":"video_encode","changed_name":"video_encode_1"},{"original_name":"video_transcode","changed_name":"video_transcode_1"}]
I want to pass this as an argument to the shell script. So,
$data = json_encode($data);
$cmd = "ssh 10.0.0.37 /usr/tmp/script.sh $data";
exec($cmd, $output);
However, I see that the argument is not correctly read by the shell script. I tried putting single quotes around $data, didn't work. Also, tried using escapeshellarg($data), still did not work.
Edit
The output of echo escapeshellarg($data) is
'[{"original_name":"pdf_convert","changed_name":"pdf_convert_1"},{"original_name":"video_encode","changed_name":"video_encode_1"},{"original_name":"video_transcode","changed_name":"video_transcode_1"}]'
Also, if there is any other format which can be parsed easily in a shell script, then I would lie to use that format (not necessarily JSON). I see that I may have to use 'jq' to parse json which needs me to install an additional package.
Bash isn't very good at accepting a JSON string in as arguments...
One way to get around bash trying to parse the arguments is for your php script to write the JSON string to a file, and for the bash script to parse that file with jq
I was able to use serilaize to send the json data. Below is the code.
$data = json_encode($arg)
$data = escapeshellarg($data);
$data = serialize($data);
$data = str_replace('"','\"',$data);
$cmd = "ssh 10.0.0.37 /usr/tmp/script.sh $data";
I can now get the data in the shell script.
PHP:
<?php
$json = '[{"original_name":"pdf_convert","changed_name":"pdf_convert_1"},{"original_name":"video_encode","changed_name":"video_encode_1"},{"original_name":"video_transcode","changed_name":"video_transcode_1"}]';
$cmd = $json;
$cmd = addslashes($cmd);
// addslashes does not escapes curly braces
$cmd = strtr($cmd, array('{' => '\\{', '}' => '\\}'));
$cmd = escapeshellarg($cmd);
$cmd = "ssh localhost echo $cmd";
echo "\n$cmd\n\n";
exec($cmd, $output);
var_dump($output)
Shell (/tmp/1.sh):
#!/bin/sh
echo "$1"
Shell Output:
ssh localhost /tmp/1.sh '[\{\"original_name\":\"pdf_convert\",\"changed_name\":\"pdf_convert_1\"\},\{\"original_name\":\"video_encode\",\"changed_name\":\"video_encode_1\"\},\{\"original_name\":\"video_transcode\",\"changed_name\":\"video_transcode_1\"\}]'
array(1) {
[0]=>
string(200) "[{"original_name":"pdf_convert","changed_name":"pdf_convert_1"},{"original_name":"video_encode","changed_name":"video_encode_1"},{"original_name":"video_transcode","changed_name":"video_transcode_1"}]"
}

Executing python commands from php script

I have installed SymPi in the server and from the command line, I am able to execute the following.
python ./sympy-0.7.5/bin/isympy
(this will open a console where I can type mathematical expressions. then the following expression)
1 + 2
(will give 3 as output)
My aim is to do the same from php using shell_exec. I have written a php file as given below, but is not working.
$command = escapeshellcmd('python ./sympy-0.7.5/bin/isympy');
shell_exec($command);
$output = shell_exec('1 + 2');
Can anybody help me to figure out why this is not working?
Please note that the following script works fine which just execute a python script and retrieve the output.
$command = escapeshellcmd('python C:\PythonPrograms\test3.py');
$output = shell_exec($command);
echo $output;
My guess is that the working directory (cwd) of shell_exec is different from the one you're in when you execute it manually.
Your working example specifies a hard path that will work from anywhere. Whereas your not-working example specifies a relative path (./ is the cwd).
Convert your call to isympy to give its full path on disk. Or figure out how to set the cwd of shell_exec.
(If this doesn't solve it, say more than "is not working." What happens? An error? What is the full text of the error?)
Each time you run shell_exec, it opens a completely new instance of the shell.
Edit:
You can pass a command for python to execute like this:
$expression = '1 + 2';
$cmd = 'python -c \'print "%f" % (' . $expression . ')\'';
$output = shell_exec($cmd);
This, admittedly is not using sympy, but for simple mathmatical expressions you may not need to. If you do, you would just need to import the library in the same command, like this: python -c 'import sympy; print "%f" % sympy.sqrt(3)'
I could manage the desired result in a different way.
Created a python script which accepts the expression as the command line argument , execute and display the output.
Call this script from php by passing the expression as the command line argument.

How to capture multi-line output for commands issued with PHP exec?

I am trying to execute system commands in PHP and capture the output of those commands where that output covers multiple lines. I am using exec(), but it seems like it only returns a value for commands that generate output on a single line.
For example, if I run date at the command line I get:
Wed May 15 15:07:32 EST 2013
As expected, if I run this command from PHP as an exec using this...
exec("date", $exec_results);
...then the value of $exec_results becomes...
Array ( [0] => Wed May 15 15:07:32 EST 2013 )
However, when I run time from the command line I get this...
real 0m0.000s
user 0m0.000s
sys 0m0.000s
...but when I do it from PHP with this...
exec("time", $exec_results);
... the value of $exec_results is empty:
Array( )
I don't actually need to run date or time in my application but these are just examples of how the single line vs. multi-line output on the command line seems to change what gets back to PHP.
The documents say:
If the output argument is present, then the specified array will be filled with every line of output from the command.
So why is the $exec_results array not being filled with all the lines seen when the time command is run in the command line?
Notes - I have run the command line entries as the apache user to rule out privileges.
This should work for you
ob_start();
passthru("ls -la");
$dat = ob_get_clean();
So here's the full list:
system() => Execute an external program and displays the output.
passthru() => Same than system, but casts the output in binary "as is" from the shell to the PHP output (typically the HTTP response).
exec() => Captures the output and only the last line of the output into a string.
shell_exec() => Same than exec, but capturing full output, not only the last line.
So, my preference: Always use shell_exec() and then do with the full-string whatever you want.
How to test
$ php -a
Interactive mode enabled
php > echo( shell_exec( "echo hello; echo bye" ) );
hello
bye
php >
https://www.php.net/manual/en/function.shell-exec.php
I changed my post for the working solution:
Use the 'script' command of unix to get the result.
you will surely have to remove "extra lines" of the temporary log file.
exec('script -c "time" /tmp/yourfile.txt');
$result = file('/tmp/yourfile.txt');
var_dump($result);
You should always put a full path to your temporary file, anywhere you put it
that's it !

piping data into command line php?

It is possible to pipe data using unix pipes into a command-line php script? I've tried
$> data | php script.php
But the expected data did not show up in $argv. Is there a way to do this?
PHP can read from standard input, and also provides a nice shortcut for it: STDIN.
With it, you can use things like stream_get_contents and others to do things like:
$data = stream_get_contents(STDIN);
This will just dump all the piped data into $data.
If you want to start processing before all data is read, or the input size is too big to fit into a variable, you can use:
while(!feof(STDIN)){
$line = fgets(STDIN);
}
STDIN is just a shortcut of $fh = fopen("php://stdin", "r");.
The same methods can be applied to reading and writing files, and tcp streams.
As I understand it, $argv will show the arguments of the program, in other words:
php script.php arg1 arg2 arg3
But if you pipe data into PHP, you will have to read it from standard input. I've never tried this, but I think it's something like this:
$fp = readfile("php://stdin");
// read $fp as if it were a file
If your data is on one like, you can also use either the -F or -R flag (-F reads & executes the file following it, -R executes it literally) If you use these flags the string that has been piped in will appear in the (regular) global variable $argn
Simple example:
echo "hello world" | php -R 'echo str_replace("world","stackoverflow", $argn);'
You can pipe data in, yes. But it won't appear in $argv. It'll go to stdin. You can read this several ways, including fopen('php://stdin','r')
There are good examples in the manual
This worked for me:
stream_get_contents(fopen("php://stdin", "r"));
Came upon this post looking to make a script that behaves like a shell script, executing another command for each line of the input... ex:
ls -ln | awk '{print $9}'
If you're looking to make a php script that behaves in a similar way, this worked for me:
#!/usr/bin/php
<?php
$input = stream_get_contents(fopen("php://stdin", "r"));
$lines = explode("\n", $input);
foreach($lines as $line) {
$command = "php next_script.php '" . $line . "'";
$output = shell_exec($command);
echo $output;
}
If you want it to show up in $argv, try this:
echo "Whatever you want" | xargs php script.php
That would covert whatever goes into standard input into command line arguments.
Best option is to use -r option and take the data from the stdin. Ie I use it to easily decode JSON using PHP.
This way you don't have to create physical script file.
It goes like this:
docker inspect $1|php -r '$a=json_decode(stream_get_contents(STDIN),true);echo str_replace(["Array",":"],["Shares"," --> "],print_r($a[0]["HostConfig"]["Binds"],true));'
This piece of code will display shared folders between host & a container.
Please replace $1 by the container name or put it in a bash alias like ie displayshares() { ... }
I needed to take a CSV file and convert it to a TSV file. Sure, I could import the file into Excel and then re-export it, but where's the fun in that when piping the data through a converter means I can stay in the commandline and get the job done easily!
So, my script (called csv2tsv) is
#!/usr/bin/php
<?php
while(!feof(STDIN)){
echo implode("\t", str_getcsv(fgets(STDIN))), PHP_EOL;
}
I chmod +x csv2tsv.
I can then run it cat data.csv | csv2tsv > data.tsv and I now have my data as a TSV!
OK. No error checking (is the data an actual CSV file?), etc. but the principle works well.
And of course, you can chain as many commands as you need.
If you are wanting more to expand on this idea, then how about the ability to include additional options to your command?
Simple!
#!/usr/bin/php
<?php
$separator = $argv[1] ?? "\t";
while(!feof(STDIN)){
echo implode($separator, str_getcsv(fgets(STDIN))), PHP_EOL;
}
Now I can overwrite the default separator from being a tab to something else. A | maybe!
cat data.csv | csv2tsv '|' > data.psv
Hope this helps and allows you to see how much more you can do!

Categories