On my synology I have webstation up and running (tested) Default server is Apache 2.4.
By default, on DSM 7, Python is installed. Now I created a simple test.py script which I call from my browser:
#!/usr/bin/python
import os
print ("Content-type: text/html\n\n")
print ("<html>Hello world!</html>")
if 'REQUEST_METHOD' in os.environ :
print ("This is a webpage")
else :
print ("This is not a webpage")
When I run this "192.bla.bla/web/test.py" the code is not executed but just displayed. So I get this in my browser:
#!/usr/bin/python
import os
print ("Content-type: text/html\n\n")
print ("<html>Hello world!</html>")
if 'REQUEST_METHOD' in os.environ :
print ("This is a webpage")
else :
print ("This is not a webpage")
Obviously Python is not executed so I searched the internet and found this, outdated German, topic: Link to Topic
Telling me to change some config files. However the directories these files should contain are not on my system. I'm also not sure if this even is the solution as this topic is outdated.
Does anyone have Python running on Synology webstation?
Try using a php server and page and then using this in the index.php
<?php
$command = escapeshellcmd('/usr/custom/test.py');
$output = shell_exec($command);
echo $output;
?>
Related
I can run below script to print lines from the file in PHP so it looks like PHP has appropriate permissions but I'm not entirely sure. I also tried to make script executable, but no change. Below script works from shell and it writes passed argument to file. What do I miss?
Python script:
#!/usr/bin/python3
import sys
ip = sys.argv[1]
with open('/var/www/public_html/images/.htaccess') as file:
lines = file.readlines()
print(lines)
if not ip in file.read():
lines = [line.rstrip() for line in lines]
lines.insert(-1,' Require ip '+ip)
with open('/var/www/public_html/images/.htaccess','w') as f:
for a in lines:
f.write(a+'\n')
PHP script:
$ip = $_SERVER['REMOTE_ADDR'];
$command = escapeshellcmd('/var/www/public_html/cgi-bin/test.py');
$output = shell_exec($command).$ip;
echo $output
pass the $ip argument inside the escapeshellcmd(). Also if you suffer from bad permission issues try to provide your python script as an input to python interpreter:
$ip = $_SERVER['REMOTE_ADDR'];
$command = escapeshellcmd('/usr/bin/python3 /var/www/public_html/cgi-bin/test.py '.$ip);
$output = shell_exec($command);
echo $output
Also, I don't think your php script has enough access rights to patch .htaccess file. If so - it's web server misconfiguration, so the idea of this script is very questionable.
maybe your server dont have the wsgi module
try to run on terminal:
a2enmod wsgi
I want to execute Python script from PHP file. I am able to execute simple python script like:
print("Hello World")
but when I want to execute following script, nothing happens
from pydub import AudioSegment
AudioSegment.converter = "/usr/bin/ffmpeg"
sound = AudioSegment.from_file("/var/www/dev.com/public_html/track.mp3")
sound.export("/var/www/dev.com/public_html/test.mp3", format="mp3", bitrate="96k")
and same script works fine when I execute it from terminal. here is my php script:
$output = shell_exec("/usr/bin/python /var/www/dev.com/public_html/index.py");
echo $output;
I have also tried following method but no luck:
$output = array();
$output = passthru("/usr/bin/python /var/www/dev.com/public_html/index.py");
print_r($output);
please help me
PHP's passthru function does not have the elegant method for which you may be searching of passing environment variables. If you must use passthru, then export your variables directly in the command:
passthru("SOMEVAR=$yourVar PATH=$newPATH ... /path/to/executable $arg1 $arg2 ...")
If you are inclined toward shell_exec, you may appreciate putenv for the slightly cleaner interface:
putenv("SOMEVAR=$yourVar");
putenv("PATH=$newPATH");
echo shell_exec("/path/to/executable $arg1 $arg2 ...");
If you are open to a more robust (if tedious) approach, consider proc_open:
$cmd = "/path/to/executable arg1 arg2 ..."
# Files 0, 1, 2 are the standard "stdin", "stdout", and "stderr"; For details
# read the PHP docs on proc_open. The key here is to give the child process a
# pipe to write to, and from which we will read and handle the "passthru"
# ourselves
$fileDescriptors = array(
0 => ["pipe", "r"],
1 => ["pipe", "w"],
2 => ["pipe", "w"]
);
$cwd = '/tmp';
$env = [
'PATH' => $newPATH,
'SOMEVAR' => $someVar,
...
];
# "pHandle" = "Process handle". Note that $pipes is new here, and will be
# given back to us
$pHandle = proc_open($cmd, $fileDescriptors, $pipes, $cwd, $env);
# crucial: did proc_open work?
if ( is_resource( $pHandle ) ) {
# $pipes is now valid
$pstdout = $pipes[ 1 ];
# Hey, whaddya know? PHP has just what we need...
fpassthru( $pstdout );
# Whenever you proc_open, you must also proc_close. Just don't
# forget to close any open file handles
fclose( $pipes[0] );
fclose( $pipes[1] );
fclose( $pipes[2] );
proc_close( $pHandle );
}
Acc to your reply, as you want to execute the python script from PHP
I was able to execute it using the following code
$command = escapeshellcmd('/var/www/yourscript.py');
$output = shell_exec($command);
echo $output;
Please use the above PHP code with the same python script.
Try to run the python script as a GCI script first to make sure it is working and set the permissions to public directory and script as I mentioned before
===================old ans============================
From what you asked, I guess this is what you are trying to do is that you are trying to run it as a CGI script like http://localhost/yourscript.py
And why are you using PHP to execute python script when you can run it directly as a CGI script?
here is what you need to do to make it work like a web page:
enable python CGI in apache ( or in the web server you are using ).
put the script in CGI configured directory
add proper code to your script to make it work as a CGI script
#!/usr/local/bin/python
from pydub import AudioSegment
AudioSegment.converter = "/usr/local/bin/ffmpeg"
sound = AudioSegment.from_file("/var/www/dev.com/public_html/track.mp3")
sound.export("/var/www/dev.com/public_html/test.mp3", format="mp3", bitrate="96k")
print "Content-type: text/html"
print
print ""
print ""
print ""
print "Done/ you can perform some conditions and print useful info here"
print ""
Give permissions to the script and make the public directory writable
Access the script http://localhost/your-path-to-script.py
I was able to run this properly.
let me know if that's not your case if you want something else
In my case, I did this code.
<?php
chdir('/home/pythontest') ; // python code dir
$commandline="/usr/bin/python3 test.py parameter" ;
exec($commandline, $output, $error) ;
echo $output ;
?>
If you need to set some environments for python, add environment vars like this.
$commmandline="LANG=en_US.utf8 LC_ALL=en_US.utf8 /usr/bin/python3 ..." ;
and check the httpd log.
Check this:
The apache user has to be in sudoers file, better you don't give sudo to apache instead give apache (www-data) user right to run your python program
put first line in your python script: #!/usr/bin/env python so the script knows which program to open it with..
then,
change group:
chgrp www-data /path/to/python-script.py
make it executabe:
chmod +x /path/to/python-script.py
then try it:
shell_exec("/path/to/python-script.py");
I hope this will work! :)
You can also exec ffmpeg directly without python:
$output = shell_exec("/usr/bin/ffmpeg -i in.mp3 -b:a 96k out.mp3");
echo $output;
ffmpeg docs
Answered in 2022.
In php 8.0 and above the following method worked. Above answers are very useful but i am compiling few extra steps here.
PHP Code.
$output = shell_exec("python3 /var/www/python/test.py");
print_r($output);
exec('python3 --version 2>&1', $output);
var_dump($output);
Trying both shell_exe and exec
Make sure the python file has executable permission and added to www-data group (if its ubuntu/debian systems) . sudo chmod +x test.py and sudo chgrp www-data test.py
Make sure the php.ini has disabled_functions line commented or empty.
sudo vim sudo vim /etc/php/8.0/cli/php.ini
sudo vim sudo vim /etc/php/8.0/apache2/php.ini
For both.
I compiled a simple video to make sure others dont spend more time figuring out the problem. https://youtu.be/t-f6b71jyoM
I have a VPS server with Apache on it. I want to execute simple CGI script. I created a python script, saved it as .cgi file and placed it to the folder cgi-bin, but it only displays error message: "End of script output before headers".
However when I saved this script as .py file and did not place it into cgi-bin folder, it worked, but whenever there was an error, it did not show any error message, just server error. Command cgitb.enable() did not show any error.
I tried to give the file 755 permission, but that still did not solve my problem.
Where could be a problem?
Source code:
#!/usr/local/bin/python3
print("Content-type:text/html")
print("")
print ("<html><head><title>CGI</title></head>")
print ("<body>")
print ("hello cgi")
print ("</body>")
print ("</html>")
Thank you for your answers.
It might be more useful to use sys.stdout.write and add \n so that you know exactly what gets written to standard output:
#!/usr/bin/env python
import sys
import os
sys.stdout.write('Status: 200 OK\n')
sys.stdout.write('Content-Type: text/html; charset=utf-8\n\n')
sys.stdout.write('<html><body>Hello, world!</body></html>\n')
sys.exit(os.EX_OK)
Run the script with python script.py | cat -e so that you can verify line endings.
Make sure you aren't sending any more HTTP headers after you start sending content.
I want to build an interface for browsing an Apache2 server using python scripts.
I spent the past days learning python and today getting familiar with CGI. I want to test out some stuff, like the possibility for the user to navigate to the path he wants from the base directory
/var/www/cgi-bin
by inputting the path he wants to visit, for example
/etc/httpd/conf.d.
For that i have the change_path.py script which looks like this:
import os
def changePath(path):
os.chdir(path)
I already got this script running to make sure everything is set up properly:
#!/usr/bin/python
# Import modules for CGI handling
import cgi, cgitb, os
cwd = os.getcwd()
print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>TestScript</title>"
print "</head>"
print "<body>"
print "<h2> Current working directory is: %s</h2>" % cwd
print "</body>"
Thanks in advance for any help. I am fairly new to python and even newer to html.
I have been trying the last few days to create a web page with buttons to perform tasks on a home server.
At the moment I have a python script that generates a page with buttons:
(See the simplified example below. removed code to clean up post)
Then a python script which runs said command and outputs to an iframe on the page:
(See the simplified example below. removed code to clean up post)
This does output the entire finished output after the command is finished. I have also tried adding the -u option to the python script to run it unbuffered. I have also tried using the Python subprocess as well. If it helps the types of commands I am running are apt-get update, and other Python scripts for moving files and fixing folder permissions.
And when run from normal Ubuntu server terminal it runs fine and outputs in real time and from my research it should be outputting as the command is run.
Can anyone tell me where I am going wrong? Should I be using a different language to perform this function?
EDIT Simplified example:
initial page:
#runcmd.html
<head>
<title>Admin Tasks</title>
</head>
<center>
<iframe src="/scripts/python/test/createbutton.py" width="650" height="800" frameborder="0" ALLOWTRANSPARENCY="true"></iframe>
<iframe width="650" height="800" frameborder="0" ALLOWTRANSPARENCY="true" name="display"></iframe>
</center>
script that creates button:
cmd_page = '<form action="/scripts/python/test/runcmd.py" method="post" target="display" >' + '<label for="run_update">run updates</label><br>' + '<input align="Left" type="submit" value="runupdate" name="update" title="run_update">' + "</form><br>" + "\n"
print ("Content-type: text/html")
print ''
print cmd_page
script that should run command:
# runcmd.py:
import os
import pexpect
import cgi
import cgitb
import sys
cgitb.enable()
fs = cgi.FieldStorage()
sc_command = fs.getvalue("update")
if sc_command == "runupdate":
cmd = "/usr/bin/sudo apt-get update"
pd = pexpect.spawn(cmd, timeout=None, logfile=sys.stdout)
print ("Content-type: text/html")
print ''
print "<pre>"
line = pd.readline()
while line:
line = pd.readline()
I havent tested the above simplified example so unsure if its functional.
EDIT:
Simplified example should work now.
Edit:
Imrans code below if I open a browser to the ip:8000 it displays the output just like it was running in a terminal which is Exactly what I want. Except I am using Apache server for my website and an iframe to display the output. How do I do that with Apache?
edit:
I now have the output going to the iframe using Imrans example below but it still seems to buffer for example:
If I have it (the script through the web server using curl ip:8000) run apt-get update in terminal it runs fine but when outputting to the web page it seems to buffer a couple of lines => output => buffer => ouput till the command is done.
But running other python scripts the same way buffer then output everything at once even with the -u flag. While again in terminal running curl ip:800 outputs like normal.
Is that just how it is supposed to work?
EDIT 19-03-2014:
any bash / shell command I run using Imrans way seems to output to the iframe in near realtime. But if I run any kind of python script through it the output is buffered then sent to the iframe.
Do I possibly need to PIPE the output of the python script that is run by the script that runs the web server?
You need to use HTTP chunked transfer encoding to stream unbuffered command line output. CherryPy's wsgiserver module has built-in support for chunked transfer encoding. WSGI applications can be either functions that return list of strings, or generators that produces strings. If you use a generator as WSGI application, CherryPy will use chunked transfer automatically.
Let's assume this is the program, of which the output will be streamed.
# slowprint.py
import sys
import time
for i in xrange(5):
print i
sys.stdout.flush()
time.sleep(1)
This is our web server.
2014 Version (Older cherrpy Version)
# webserver.py
import subprocess
from cherrypy import wsgiserver
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/plain')])
proc = subprocess.Popen(['python', 'slowprint.py'], stdout=subprocess.PIPE)
line = proc.stdout.readline()
while line:
yield line
line = proc.stdout.readline()
server = wsgiserver.CherryPyWSGIServer(('0.0.0.0', 8000), application)
server.start()
2018 Version
#!/usr/bin/env python2
# webserver.py
import subprocess
import cherrypy
class Root(object):
def index(self):
def content():
proc = subprocess.Popen(['python', 'slowprint.py'], stdout=subprocess.PIPE)
line = proc.stdout.readline()
while line:
yield line
line = proc.stdout.readline()
return content()
index.exposed = True
index._cp_config = {'response.stream': True}
cherrypy.quickstart(Root())
Start the server with python webapp.py, then in another terminal make a request with curl, and watch output being printed line by line
curl 'http://localhost:8000'