I'm trying to run a Python script from PHP using the following command:
exec('/usr/bin/python2.7 /srv/http/assets/py/switch.py arg1 arg2');
However, PHP simply doesn't produce any output. Error reporting is set to E_ALL and display_errors is on.
Here's what I've tried:
python2
, /usr/bin/python2
and python2.7
instead of /usr/bin/python2.7
exec
, shell_exec
, system
.However, if I run
if (exec('echo TEST') == 'TEST')
{
echo 'exec works!';
}
it works perfectly fine while shutdown now
doesn't do anything.
PHP has the permissions to access and execute the file.
EDIT: Thanks to Alejandro, I was able to fix the problem. If you have the same problem, don't forget that your webserver probably/hopefully doesn't run as root. Try logging in as your webserver's user or a user with similar permissions and try to run the commands yourself.
The above methods seem to be complex. Use my method as a reference.
I have these two files:
run.php
mkdir.py
Here, I've created an HTML page which contains a GO button. Whenever you press this button a new folder will be created in directory whose path you have mentioned.
run.php
<html>_x000D_
<body>_x000D_
<head>_x000D_
<title>_x000D_
run_x000D_
</title>_x000D_
</head>_x000D_
_x000D_
<form method="post">_x000D_
_x000D_
<input type="submit" value="GO" name="GO">_x000D_
</form>_x000D_
</body>_x000D_
</html>_x000D_
_x000D_
<?php_x000D_
if(isset($_POST['GO']))_x000D_
{_x000D_
shell_exec("python /var/www/html/lab/mkdir.py");_x000D_
echo"success";_x000D_
}_x000D_
?>
_x000D_
mkdir.py
#!/usr/bin/env python
import os
os.makedirs("thisfolder");
To clarify which command to use based on the situation
exec()
- Execute an external program
system()
- Execute an external program and display the output
passthru()
- Execute an external program and display raw output
Alejandro nailed it, adding clarification to the exception (Ubuntu or Debian) - I don't have the rep to add to the answer itself:
sudoers file:
sudo visudo
exception added:
www-data ALL=(ALL) NOPASSWD: ALL
In my case I needed to create a new folder in the www
directory called scripts
. Within scripts
I added a new file called test.py
.
I then used sudo chown www-data:root scripts
and sudo chown www-data:root test.py
.
Then I went to the new scripts
directory and used sudo chmod +x test.py
.
My test.py file it looks like this. Note the different Python version:
#!/usr/bin/env python3.5
print("Hello World!")
From php I now do this:
$message = exec("/var/www/scripts/test.py 2>&1");
print_r($message);
And you should see: Hello World!
If you want to know the return status of the command and get the entire stdout
output you can actually use exec
:
$command = 'ls';
exec($command, $out, $status);
$out
is an array of all lines. $status
is the return status. Very useful for debugging.
If you also want to see the stderr
output you can either play with proc_open or simply add 2>&1
to your $command
. The latter is often sufficient to get things working and way faster to "implement".
This is so trivial, but just wanted to help anyone who already followed along Alejandro's suggestion but encountered this error:
sh: blabla.py: command not found
If anyone encountered that error, then a little change needs to be made to the php file by Alejandro:
$command = escapeshellcmd('python blabla.py');
I recommend using passthru
and handling the output buffer directly:
ob_start();
passthru('/usr/bin/python2.7 /srv/http/assets/py/switch.py arg1 arg2');
$output = ob_get_clean();
All the options above create new system process. Which is a performance nightmare. For this purpose I stitched together PHP module with "transparent" calls to Python.
https://github.com/kirmorozov/runpy
It may be tricky to compile, but will save system processes and will let you keep Python runtime between PHP calls.
Inspired by Alejandro Quiroz:
<?php
$command = escapeshellcmd('python test.py');
$output = shell_exec($command);
echo $output;
?>
Need to add Python, and don't need the path.
Source: Stackoverflow.com