run python script as cgi apache server - python

I am trying to make a python script run as cgi, using an Apache server. My script looks something like this:
#!/usr/bin/python
import cgi
if __name__ == "__main__":
print("Content-type: text/html")
print("<HTML>")
print("<HEAD>")
I have done the necessary configurations in httpd.conf(in my opinion):
<Directory "/opt/lampp/htdocs/xampp/python">
Options +ExecCGI
AddHandler cgi-script .cgi .py
Order allow,deny
Allow from all
</Directory>
I have set the execution permission for the script with chmod
However, when I try to access the script via localhost i get an Error 500:End of script output before headers:script.py
What could be the problem? The script is created in an Unix like environment so I think the problem of clrf vs lf doesn't stand. Thanks a lot.

I think you are missing a print statement after
print("Content-type: text/html")
The output of a CGI script should consist of two sections, separated by a blank line. The first section contains a number of headers, telling the client what kind of data is
following.
The second section is usually HTML, which allows the client software to display nicely formatted text with header, in-line images, etc.
It may look like
#!/usr/bin/env python
print "Content-Type: text/html"
print
print """
<TITLE>CGI script ! Python</TITLE>
<H1>This is my first CGI script</H1>
Hello, world!
"""
For more details visit python-cgi
For python3
#!/usr/bin/env python3
print("Content-Type: text/html")
print()
print ("""
<TITLE>CGI script ! Python</TITLE>
<H1>This is my first CGI script</H1>
Hello, world!
"""
)

Related

Passing a list as variable to python script from bash script

I have a python script like below.
# Import necessary libraries and functions
import sys
import traceback
y = '2020'
querysting = "select {} from table where Year={}".format(col_list,y)
df = pd.read_sql(querystring,db)
if __name__ == '__main__':
if len(sys.argv) != 8:
print('Invalid number of args......')
print('Usage: file.py Input_path Output_path')
exit()
_, col_list, FinalDB, final_table, host, dsl_tbl_name, username, password = tuple(sys.argv)
data_load(col_list, FinalDB, final_table, host, tbl_name, username, password)
Now I am calling this python script inside a shell script like below
#!/bin/bash
col_list='id, name, address, phone_number'
FinalDB='abc'
final_table='xyz'
host='xxxxxx.xxxx'
tbl_name='test'
username='USER'
password='test_pass'
python python_script.py ${col_list} ${FinalDB} ${final_table} ${host} ${tbl_name} ${username} ${password}
Now when I run this bash script I am getting Invalid number of args...... error
I am pretty much sure that it is some thing to do with col_list variable being passed to the python script.
Because instead of having columns in a list if I just pass select * in the query and removing col_list variable then I don't get any errors
What am I doing wrong here and how can I resolve this issue.
The problem comes from how you pass your variables that contains spaces from Bash to Python.
You may note that:
In shell scripts command line arguments are separated by
whitespace, unless the arguments are quoted.
Let's have this simple Python script:
python_script.py:
import sys
if __name__ == '__main__':
print(sys.arv)
Then in your Terminal:
$> export var1="hello"
$> python python_script.py $var1
['python_script.py', 'hello']
However:
$> export var1="hello, hi"
$> python python_script.py $var1
['python_script.py', 'hello,', 'hi'] # Note Here: Two args were passed
$> export var1="hello,hi"
$> python python_script.py $var1
['python_script.py', 'hello,hi'] # One arg passed
So, a solution to your problem, is to pass your Bash args as a string even with spaces, like this example:
$> export var1="hello, hi, hola"
$> python python_script.py "$var1"
['python_script.py', 'hello, hi, hola']
For more informations see this article

Run a .bat file from a Python CGI file with Apache Webserver

This might be really easy. But its just not working for me.
I have a .bat file I would like to run, which performs stuff on the Server, and should send an email with an Attachement.
The .bat file works fine, it sends the email with the log and everything.
Now I would like to run that file from a Webserver. So that I can click on an HTML form Button, and it executes.
I have installed Apache, Python 2.7 for it.
I have configured Apache to allow cgi files, and It works when I put a file as index.py with following code.
But when I press the Submit button it goes through, but the .bat files is not being executed. Help! :)
Is there another way I can run a .bat file to do stuff on my server from a Webserver maybe? thank you in beforehand.
I tried the action in the form to direct to a .py and .cgi file... don't get it to work
Below the code I a have been using.
#!/Python27/python
#!/usr/bin/env python
import cgi
import cgitb; cgitb.enable()
print "Content-type: text/html"
print
print "<html><head>"
print "<form action='../cgi-bin/send_email.py'>"
print "<input type='submit' value='Submit'>"
print "</form>"
send_email.py looks like this.
#!/Python27/python
#!/usr/bin/env python
import cgi
import cgitb; cgitb.enable()
from subprocess import Popen
p = Popen("batch.bat", cwd=r"C:\Path\to\batchfolder")
stdout, stderr = p.communicate()
You can invoke the batch file with cmd.exe:
...
cmd = r'c:\Windows\System32\cmd.exe'
batDir = r'C:\Path\to\batchfolder'
batName = r'batch.bat'
p = Popen(r"{0} /C {1}\{2}".format(cmd,batDir,batName), cwd=batDir)
...

How to switch users for Python CGI Programming?

I have an HTML form which is handled by a Python script using CGI programming. From my Python script, I want to switch users from apache2 to monkey. The reason is because I'm using os.system to run another script from within my Python script.
The Python script works fine but I keep getting Permission errors when executing this command: os.system('python other_script.py'). What I realize is that when I am running the HTML form, I am apache2 instead of monkey. I'd like to know how to switch users (as monkey not root) while executing the Python script.
Here is what my Python script looks like:
#!/usr/bin/python -W
# Import modules for CGI handling
import cgi, cgitb
import pwd
import grp
import sys
import os
# Create instance of FieldStorage
form = cgi.FieldStorage()
print "Content-type:text/html\r\n\r\n"
print '<html>'
print '<head>'
print '<title>Hello Word - First CGI Program</title>'
print '</head>'
print '<body>'
print '</body>'
print '</html>'
os.system('python other_script.py') # getting permission errors here

python cgi script is not executing in XAMPP

i am a beginner in python. I've installed python34, and xampp. I've changed the http.config file and added the .py extension in handler block. then i put my python script into xamp/bin-cgi and set the first line of the python script as, "#!C:/Python34/python.exe". But when i opens the file through localhost/cgi-bin/test.py it doesn't showing anything only a blank screen, Below the content of the file.
#!C:/Python34/python.exe
print "Content-type: text/html"
print
print "<html>"
print "<head>"
print "<title>welcome cgi</title>"
print "</head>"
print "<body>"
print "<h1>first python page</h1>"
print "<p>heihei</p>"
print "</body>"
print "</html>"
You should rewrite the first line like this:
#!"C:\Python34\python.exe"
You are using Python 2.7 with your print statements. That is the first error. YOu are calling the Python 3.4 interpreters.
Also, you need to change your first line to
#!/Python34/python
# -*- coding: UTF-8 -*-
# enable debugging
Then, change your print statements to have parentheses
print("Content-type: text/html")
print()
print("""<html>
<head>
<title>welcome cgi</title>
</head>
<body>
<h1>first python page</h1>
<p>heihei</p>
</body>
</html>""")
ATTENTION:
If you notice, I changed up your code a bit and got rid of a bunch of print statements. Instead, I used what's called a multiline string (instead of writing "blah" I would do """blah"""). For example if I did
print("asdasdasd
asdasdasdasdasd")
This wouldn't work
But, if I changed it to
print("""asdasdasdasdasd
asdasdasdasdasd""")
This would be a perfectly acceptable command. Every new line would be registered as a "\n" so really, the string we are printing out is "asdasdasdasdasd\nasdasdasdasdasd" where \n marks a new line

How can I serve unbuffered CGI content from Apache 2?

I would like to be able to allow a user to view the output of a long-running GCI script as it is generated rather than after the script is complete. However even when I explicitly flush STDOUT the server seems to wait for the script to complete before sending the response to the client. This is on a Linux server running Apache 2.2.9.
Example python CGI:
#!/usr/bin/python
import time
import sys
print "Content-type: text/plain"
print
for i in range(1, 10):
print i
sys.stdout.flush()
time.sleep(1)
print "Done."
Similar example in perl:
#!/usr/bin/perl
print "Content-type: text/plain\n\n";
for ($i = 1; $i <= 10 ; $i++) {
print "$i\n";
sleep(1);
}
print "Done.";
This link says as of Apache 1.3 CGI output should be unbuffered (but this might apply only to Apache 1.x): http://httpd.apache.org/docs/1.3/misc/FAQ-F.html#nph-scripts
Any ideas?
Randal Schwartz's article Watching long processes through CGI explains a different (and IMHO, better) way of watching a long running process.
Flushing STDOUT can help. For example, the following Perl program should work as intended:
#!/usr/bin/perl
use strict;
use warnings;
local $| = 1;
print "Content-type: text/plain\n\n";
for ( my $i = 1 ; $i <= 10 ; $i++ ) {
print "$i\n";
sleep(1);
}
print "Done.";
You must put your push script into a special directory wich contain a special .htaccess
with this environnment specs:
Options +ExecCGI
AddHandler cgi-script .cgi .sh .pl .py
SetEnvIfNoCase Content-Type \
"^multipart/form-data;" "MODSEC_NOPOSTBUFFERING=Do not buffer file uploads"
SetEnv no-gzip dont-vary
According to CGI::Push,
Apache web server from version 1.3b2
on does not need server push scripts
installed as NPH scripts: the -nph
parameter to do_push() may be set to a
false value to disable the extra
headers needed by an NPH script.
You just have to find do_push equivalent in python.
Edit: Take a look at CherryPy: Streaming the response body.
When you set the config entry "response.stream" to True (and use "yield") CherryPy manages the conversation between the HTTP server and your code like this:
(source: cherrypy.org)

Categories