Bringing Python Command Line Scripts to the Web with CGI: The Forgotten Technique

In the world of web development, modern frameworks like Flask, Django, and FastAPI dominate the landscape. However, there’s a simpler, often forgotten method to run Python scripts as webpages: CGI (Common Gateway Interface).

CGI allows you to execute command-line scripts directly on a web server and return the output to the browser. While it’s not as feature-rich as modern frameworks, it’s a lightweight and straightforward way to expose Python scripts to the web.


What is CGI?

CGI is a protocol that enables a web server to execute scripts and return their output as dynamic web content. It’s been around since the early days of the web and works by passing HTTP request data (like form inputs) to a script via environment variables or standard input. The script processes the data and outputs HTML (or other content) to the browser.


Setting Up CGI with Nginx

To run Python scripts as CGI with Nginx, you’ll need a few things:

1. A Python script to execute.

2. A CGI wrapper (like `fcgiwrap`) to handle requests.

3. Proper Nginx configuration.


Here’s how you can set it up:


1. Install `fcgiwrap`

First, install `fcgiwrap`, a FastCGI wrapper for CGI scripts:


sudo apt install fcgiwrap



2. Configure Nginx

Edit your Nginx configuration file (e.g., `/etc/nginx/sites-enabled/default`) and add a location block for CGI scripts:


server {

    ...


    location /cgi-bin/ {

        root /var/www;

        fastcgi_pass unix:/var/run/fcgiwrap.socket;

        include fastcgi_params;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

    }

}


This configuration tells Nginx to pass requests to the `/cgi-bin/` directory to the `fcgiwrap` process.


3. Create a Python Script

Create a simple Python script, e.g., `/home/user/script.py`:


#!/usr/bin/env python3

print("Working!")


Make sure the script is executable:


chmod +x /home/user/script.py



4. Set Up Sudo Permissions

Since `fcgiwrap` runs as the `www-data` user, you’ll need to allow it to execute your script as you - in case you have other dependencies that are installed only for your user. Add this line to `/etc/sudoers` using `visudo`:


www-data ALL=(user) NOPASSWD:/home/user/script.py

Make sure to replace "user" with your actual name!


5. Create a CGI Executor

Create a CGI script in `/var/www/cgi-bin/works.cgi` that calls your Python script:


#!/usr/bin/env python3


import cgi

import cgitb

import subprocess


cgitb.enable()


print("Content-Type: text/html\n")


try:

    result = subprocess.run(

        ["sudo", "-u", "user", "/home/user/script.py"],

        capture_output=True,

        text=True

    )

    if result.returncode == 0:

        print("<h1>Script executed successfully.</h1>")

        print(f"<pre>{result.stdout}</pre>")

    else:

        print(f"<h1>Error executing script:</h1><pre>{result.stderr}</pre>")

except Exception as e:

    print(f"<h1>Error:</h1><p>{str(e)}</p>")


 Make sure to replace "user" with your actual name!


Make this script executable as well:

chmod +x /var/www/cgi-bin/works.cgi



6. Test It

Restart Nginx to apply the changes:

sudo systemctl restart nginx


Then, visit 

http://localhost/cgi-bin/works.cgi 

in your browser. You should see the output of your Python script!


Why Use CGI?

While CGI isn’t as performant or scalable as modern frameworks, it’s a quick and simple way to expose command-line scripts to the web - like local services. It’s perfect for small, single-purpose tools or internal utilities where simplicity trumps feature-richness.


Give it a try and rediscover this forgotten gem of web development!

Comments

Popular posts from this blog

MurMurHash3, an ultra fast hash algorithm for C# / .NET

Quick select algorithm - find the Kth element in a list in linear time

Convert animated WEBP to MP4