Loading...
X

How to install Python as a CGI module in Apache on Linux

Table of contents

1. How to run a Python script on a web server

2. How to set up Python as a CGI module in Apache on Debian (Ubuntu, Linux Mint, Kali Linux)

2.1 Setting up Python CGI for a single directory

2.2 Setting up Python CGI for the entire web server

3. How to set up Python as a CGI module in Apache on Arch Linux (Manjaro, BlackArch)

3.1 Setting up Python CGI for a single directory

3.2 Setting up Python CGI for the entire web server

4. Errors when configuring Python CGI

4.1 Instead of executing, the web server shows the source code of the Python script, or the file is downloaded instead of executing

4.2 Server error “Error 500. End of script output before headers” for Python scripts only (otherwise the webserver works fine)

4.3 Server Error “Error 500. malformed header from script 'test.py': Bad header”

4.4 Error “This site can't be reached. localhost refused to connect”

5. Useful links


How to run a Python script on a web server

Python supports the Common Gateway Interface (CGI), that is, programs (scripts) written in Python can interact with information servers, such as HTTP servers (Apache, for example).

The web server can run Python scripts and output the resulting data even if Python is not installed as a web server CGI module.

For example, in the following PHP script, the script receives data from a form using the POST method and then runs the Python program, passing the received data as command line arguments:

<?php

echo shell_exec ('python /srv/http/test-python/script.py ' . $_POST["name"] . ' ' . $_POST["surname"] . ' '. $_POST["info"]);

After the execution of the Python script is completed, the information received from script.py will be displayed.

While there are advantages to this approach – no need to configure Python as a web server CGI module – there are some drawbacks.

If Python is not installed as a CGI module, then:

  1. PHP must be used to run Python scripts
  2. Python scripts will not have direct access to data passed by GET and POST methods.

Accordingly, configuring Python as a web server CGI module makes it possible to run scripts directly and access web server environment variables directly, including data passed by GET and POST methods.

Here's how to set up Python to Apache as a CGI for two groups of distributions:

  • Debian and derivative distributions (Ubuntu, Linux Mint, Kali Linux)
  • Arch Linux derivative distributions (Manjaro, BlackArch)

The step of installing Python into the operating system is skipped, since Python is preinstalled by default for most operating systems. If you don't have Python on your Linux, install it first.

There are 2 setting options:

  • Python scripts are only processed by the CGI module if they are placed in a special directory on the web server (eg cgi-bin)
  • Python scripts are processed by the CGI module in any webserver folder

See also: How to get data from a web page using GET and POST methods in a Python script

How to set up Python as a CGI module in Apache on Debian (Ubuntu, Linux Mint, Kali Linux)

Setting up Python CGI for a single directory

Run the command to enable the CGI module:

sudo a2enmod cgi

Restart the web server for the changes to take effect:

sudo systemctl restart apache2

Create file /usr/lib/cgi-bin/test.py:

sudo gedit /usr/lib/cgi-bin/test.py

Copy the following content to this file:

#!/usr/bin/python3

print ("Content-type: text/html")
print ("")
print ("")
print ("<html><head>")
print ("")
print ("</head><body>")
print ("Hello.")
print ("</body></html>")

Make this file executable:

sudo chmod +x /usr/lib/cgi-bin/test.py

Open http://localhost/cgi-bin/test.py in a web browser

If everything is configured correctly, then you should see a line in the web browser

Hello.

Note: If instead of the /usr/lib/cgi-bin/ directory you want to use another folder for CGI scripts, then specify it in the /etc/apache2/conf-enabled/serve-cgi-bin.conf file.

Setting up Python CGI for the entire web server

Run the command to enable the CGI module:

sudo a2enmod cgi

Open the /etc/httpd/conf/httpd.conf file – the web server configuration file:

sudo gedit /etc/httpd/conf/httpd.conf

Find a group of lines there

<Directory /var/www/>
	Options Indexes FollowSymLinks
	AllowOverride None
	Require all granted
</Directory>

and replace them with

<Directory /var/www/>
	Options Indexes FollowSymLinks ExecCGI
	AllowOverride None
	Require all granted
</Directory>

ATTENTION: your set of options may be different.

Add the following line to the end of the file:

AddHandler cgi-script .cgi .py

Close the file.

Restart the web server for the changes to take effect:

sudo systemctl restart apache2

Create file /var/www/html/test.py:

sudo gedit /var/www/html/test.py

Copy the following content to this file:

#!/usr/bin/python3

print ("Content-type: text/html")
print ("")
print ("")
print ("<html><head>")
print ("")
print ("</head><body>")
print ("Hello.")
print ("</body></html>")

Make this file executable:

sudo chmod +x /var/www/html/test.py

Open http://localhost/test.py in a web browser

If everything is configured correctly, then you should see a line in the web browser

Hello.

How to set up Python as a CGI module in Apache on Arch Linux (Manjaro, BlackArch)

Setting up Python CGI for a single directory

Create a directory /srv/http/cgi-bin/ - this is where the Python scripts will be located:

sudo mkdir /srv/http/cgi-bin/

Open the /etc/httpd/conf/httpd.conf file – the web server configuration file:

sudo gedit /etc/httpd/conf/httpd.conf

Find a group of lines:

<Directory "/srv/http/cgi-bin">
    AllowOverride None
    Options None
    Require all granted
</Directory>

And replace it with:

<Directory "/srv/http/cgi-bin">
    AllowOverride None
    Options ExecCGI
    Require all granted
</Directory>

Note: if you do not see the difference, then pay attention to the “Options” directive – the “ExecCGI” option has been added.

Find a group of lines

<IfModule mpm_prefork_module>
	#LoadModule cgi_module modules/mod_cgi.so
</IfModule>

And replace with

<IfModule mpm_prefork_module>
	LoadModule cgi_module modules/mod_cgi.so
</IfModule>

That is, uncomment the line.

Notice the line

ScriptAlias /cgi-bin/ "/srv/http/cgi-bin/"

It is not necessary to change it, but if you wish, you can use any other folder instead of /srv/http/cgi-bin/, you just need to create a new folder and specify it with this directive instead of /srv/http/cgi-bin/.

Close the file.

Restart the web server for the changes to take effect:

sudo systemctl restart httpd.service

Create file /srv/http/cgi-bin/test.py:

sudo gedit /srv/http/cgi-bin/test.py

Copy the following content to this file:

#!/usr/bin/python3

print ("Content-type: text/html")
print ("")
print ("")
print ("<html><head>")
print ("")
print ("</head><body>")
print ("Hello.")
print ("</body></html>")

Make this file executable:

sudo chmod +x /srv/http/cgi-bin/test.py

Open http://localhost/cgi-bin/test.py in a web browser

If everything is configured correctly, then you should see a line in the web browser

Hello.

Setting up Python CGI for the entire web server

Open the /etc/httpd/conf/httpd.conf file – the web server configuration file:

sudo gedit /etc/httpd/conf/httpd.conf

Find a group of lines

<IfModule mpm_prefork_module>
	#LoadModule cgi_module modules/mod_cgi.so
</IfModule>

And replace with

<IfModule mpm_prefork_module>
	LoadModule cgi_module modules/mod_cgi.so
</IfModule>

That is, uncomment the line.

Then find the line

Options Indexes FollowSymLinks

and add “ExecCGI” to it. You should get the following line (ATTENTION: your set of options may be different):

Options Indexes FollowSymLinks ExecCGI

Now find the line:

#AddHandler cgi-script .cgi

Uncomment it, that is, remove the # symbol at the beginning of the line and add .py to the end of the line. The new line will look something like this:

AddHandler cgi-script .cgi .py

Close the file.

Restart the web server for the changes to take effect:

sudo systemctl restart httpd.service

Create file /srv/http/test.py:

sudo gedit /srv/http/test.py

Copy the following content to this file:

#!/usr/bin/python3

print ("Content-type: text/html")
print ("")
print ("")
print ("<html><head>")
print ("")
print ("</head><body>")
print ("Hello.")
print ("</body></html>")

Make this file executable:

sudo chmod +x /srv/http/cgi-bin/test.py

Open http://localhost/test.py in a web browser

If everything is configured correctly, then you should see a line in the web browser

Hello.

Errors when configuring Python CGI

Instead of executing, the web server shows the source code of the Python script, or the file is downloaded instead of executing

This means that the CGI setup has not been done or is not complete. The reasons may be:

  • webserver not restarted after making changes to config files
  • you edited the wrong config file
  • you have configured CGI scripts to run only in one folder, but you are trying to run the script in another

Server error “Error 500. End of script output before headers” for Python scripts only (otherwise the webserver works fine)

An example of the error that a web browser shows when trying to execute a Python script on a web server:

Server error!
The server encountered an internal error and was unable to complete your request.

Error message:
End of script output before headers: test.py

If you think this is a server error, please contact the webmaster.

Error 500

The reasons for the error can be:

  • Python file is not executable (no execute permission)
  • Python program has a syntax error that causes the script to terminate prematurely

To check if the script has permission to run, you can use the ls utility with the -l option, after which specify the full path to the file:

ls -l /srv/http/cgi-bin/test.py

Sample output:

-rwxr-xr-x 1 root root 127 May 20 13:11 /srv/http/cgi-bin/test.py

The letters “x” mean that it has privileges to run as a program.

To check for syntax errors, run the script on the command line with the full path before it:

/srv/http/cgi-bin/test.py

Server Error “Error 500. malformed header from script 'test.py': Bad header”

An example of another error:

Server error!
The server encountered an internal error and was unable to complete your request.

Error message:
malformed header from script 'test.py': Bad header: <html><head>

If you think this is a server error, please contact the webmaster.

Error 500

The key is the message “malformed header from script”, i.e. incorrect headers.

This refers to HTTP protocol headers. When Python is running as CGI, the script should start its output by sending an HTTP header followed by two blank lines.

For example, the following code will throw an error:

#!/usr/bin/python3

print ("<html><head>")
print ("")
print ("</head><body>")
print ("Hello.")
print ("</body></html>")

To avoid an error, the code should be like this:

#!/usr/bin/python3

print ("Content-type: text/html")
print ("")
print ("")
print ("<html><head>")
print ("")
print ("</head><body>")
print ("Hello.")
print ("</body></html>")

Error “This site can't be reached. localhost refused to connect”

If, after making changes to the Apache configuration file, you begin to receive an error message:

This site can’t be reached

localhost refused to connect.

It is most likely that the Apache configuration was done incorrectly, as a result of which it was not possible to restart the web server.

The error may be due to incorrect syntax.

To view the status of a web server on Debian and derivative distributions, run the command:

sudo systemctl status apache2

To view the web server status on Arch Linux and derivative distributions, run the command:

sudo systemctl status httpd.service

Useful links:


Leave Your Observation

Your email address will not be published. Required fields are marked *