I have a program that I can run on my command line but I was wondering if I could actually get it to run in php. Basically my program would have a user insert a couple values to search for, then those values would be passed on into the program for it to run. Then I would want the result of the program to be displayed
I found a function called exec() but I didn't understand it at all so I was wondering if anyone else knows a way or can help me out!
exec() runs a command on the command line, just as you desire. You can capture the output of the command in an array named as the second argument.
For example:
exec("whoami", $output);
var_dump($output);
This runs linux's "whoami" command and captures the result in the array $output. The second line displays the contents of the array. Is that similar to what you want to do?
Related
I have a python srcipt, called rainbow.py. I can run it optionally with an argument. From command line
python rainbow.py, python rainbow.py 4 works well. When I call this script from php I am unable to pass the argument.
I tried:
$argument=4;
exec("python rainbow.py 4");
exec("python rainbow.py $argument");
exec("python rainboy.py .$argument");
They make the code run like there's no valid argument. (I use duration=int(sys.argv[1] in my python code, the script needs to stop after a while, and when calling from php, always the default duration is active)
I tried
$argument="4"
too, did not work.
Can you tell me what's wrong?How can I pass this argument through? I am confident with python, but a total php newbie.
part of my php code:
$argument="2";
echo "printing line <br>";
exec("python rainbow.py $argument");//duration option does not work
part of my python code:
duration=10
try:
if sys.argv[1]!=None:
print "arg found!"
duration=int(sys.argv[1])
except: pass
print "duration:",duration
I cant see the duration printing out when calling python from php, but from LEDs I can cleary see the duration is always 10 seconds
I added sudo to the python call:
exec("sudo python rainbow.py $argument")
and it works now properly. Can someone tell me why?
The python script ran without it too, but without considering the argument.
I understand there are questions like mine already asked, but I can't figure this out even with the answers in those questions.
PHP:
<?php
$var1 = "hi";
$result = shell_exec('TestingStuff.py'.$var1);
?>
Python:
import sys
print(sys.argv[1])
Error received when running in Python:
IndexError: list index out of range
Both scripts are in the same folder.
Could someone please provide an answer with the code changes?
Error
If the Python script runs with no arguments at all, then that sys.argv[1] index is out of range.
Scripts
ExecPython.php
<?php
$var1 = "hi";
$result = shell_exec('TestingStuff.py ' . $var1);
echo "<pre>$result</pre>";
TestingStuff.py
import sys
if len(sys.argv) > 1:
print(sys.argv[1])
Demo
Explanation
We will start with the Python script. The goal is, that the script prints the first argument passed to it - without running into the "IndexError: list index out of range" error.
python TestingStuff.py 123 we want the output 123.
In Python the arguments passed to the script reside in sys.argv. It's a list. sys.argv[0] is always the script name itself (here TestingStuff.py). Using the example from above sys.argv[1] is now 123.
Handling the edge cases: "no argument" given.
python TestingStuff.py
This will result in an "IndexError: list index out of range" error, because you are trying to access a list element, which is not there. sys.argv[0] is the script name and sys.argv[1] is not set, but you are trying to print it and BAM goes the error. To avoid the error and only print the first argument, we need to make sure, that the list sys.argv contains more than one element (more than the script name). That's why i've added if len(sys.argv) > 1:.
That means: print the first argument only, if the list has more than 1 argument.
Now we can test the Python script standalone - with and without arguments.
And switch over to the PHP script.
The goal is to execute the Python script from PHP.
PHP provides several ways to execute a script, there are for instance exec(), passthru(), shell_exec(), system(). Here we are using shell_exec(). shell_exec() returns the output of the script or command we run with it.
In other words: if you run $result = shell_exec('php -v');, you'll get the PHP version lines in $result.
Here we are executing the Python script TestingStuff.py and add an argument, which is $var1. It's a string and added via concatenation to the string given to shell_exec(). The $result is echoed. I wrapped pre-tags around it, because i thought this is executed in the web/browser context. If you are using the scripts only on the CLI, you might drop the pre-tags.
Execution flow
the PHP script is executed
shell_exec() executes the Python script
shell_exec() returns the output of the Python script as $result
$result is printed by PHP via echo
I'm running a simple command in a loop
the command itself is ffmpeg, but I do not believe it's related to the issue
so, I have:
exec($exec.' 2>&1', $output, $return);
if($return)
{
foreach($output as $line)
{
file_put_contents($log_file, $line, FILE_APPEND);
}
}
This way, if anything goes wrong with the command I can read the output in the log. It works, however $output contains the entire shell history of the command. To clarify: every time an error occurs, all output that was generated by the particular command (including hundreds of successful executions from throughout the day) is dumped to the file. What should be a 5 line error being written is instead the entire 1000+ line history. I used the exact same code on CentOS and it gave me the expected output of only the output generated by the instance most recently executed.
From the documentation:
Note that if the array already contains some elements, exec() will append to the end of the array. If you do not want the function to append elements, call unset() on the array before passing it to exec().
I can't explain why it worked differently on CentOS.
I currently have a php page that my webserver serves. In order to display all the information I need to display on the page I need output from an external python script. So I have been using the exec() command of php to execute the python script and capture the output in an array of strings as follows:
$somequery = $_GET['query'];
$result = exec("python /var/www/html/query/myscript.py ".somequery."");
//some for loop to loop through entries in result and echo them.
However there are never any entries to be printed, yet when I run the command directly on the console of the server it will output correctly. I've tried echoing out the command on the webpage that I am executing and it's the correct command. The only thing I think it can be is that exec() doesn't stop the rest of the php program from executing before it finishes, leading to the loop i have printing out entries finding that $result is empty.
How can I ensure that exec() finishes executing before the rest of my php script? Are there maybe settings in php.ini that I would need to change? I'm not entirely sure.
EDIT: I've tried running and storing the output of shell_exec("echo hello"); and printing that output, it now prints. However, when running my command that takes a few seconds longer, the program never finishes executing it before going to the next line.
EDIT 2: I found my solution in the following post https://stackoverflow.com/a/6769624 My issue was with with the numpy python package I was using and I simply needed to comment out the line in /usr/lib64/python2.7/ctypes/init.py like the poster did and my script output correctly.
The correct way to get your shell output is like this:
exec("python /var/www/html/query/myscript.py ".somequery."", $result);
var_dump($result); //output should be in here
Give it a try.
I'm running a continuous PHP loop that executes another PHP file by using exec("php ...");. The plan is for the executed script to run, then sleep for 2 seconds, then start again. However, it seems like my loop is starting a new instance every 2 seconds instead. So long question short, how do I get my first php script to wait until the execution of script nr 2 is complete?
All this is run using the command line. I would also like the echo functions in script nr 2 to show up on the command line.
Any thoughts would help.
Thanks
Exec does not maintain any state information between instances. You could:
Loop in your subscript
OR
You could set some sort of environment variables or that are read at the beginning of the subscript and written at the end.
OR
You could have the subscript read/write to a file in a similar fashion
OR
You could pass in parameters to the subscript who's output is captured
For outputting to the screen, you might play around with the other exec/system calls:
exec
shell_exec
passthru
system
I believe passthru() will work. Another possibility if it doesn't is to call exec(), using the output parameters to capture the output strings from the subscript. Then just echoing that output on return of the subscript.
I also believe that using the output parameters (or capturing the result of the function in a variable) will cause the exec to wait until the command is complete before continuing on.
The problem is, once you excute the script, it will run. Another exec will start another instance like you found out.
What you can do is
Put the sleep inside the executed script. Once it starts running, it will do its own sleep. You can look at setting an execution time limit and maybe ignoring user abort.
You can create a function and let your script call that function. It will then sleep after execution and call the function again.
// maybe set time limit here
Function loop ()
{
Sleep(120);
//you can make a check whether to loop or not.
Loop();
}
Loop();