CGI scripts

Writing, installing and using CGI scripts

The CSE webservers don't just serve static html - they can also serve CGI scripts written in PHP, perl, python or virtually any programming language.

How do I write a CGI script?

A CGI script can be any executable program or script that conforms to the Common Gateway Interface protocol.

  • Write any program that outputs the correct HTTP headers.
    • At its most basic, ensure that it sends Content-type: text/html followed by a blank line, before any other output.
  • Give it a filename ending in .cgi, .py, .pl, .sh, .shtml or .php, as appropriate - or see below.
  • Place it anywhere under your public_html directory.
  • Set it exectutable by running chmod u+x filename
  • Access the file over the web at

If you're using PHP:

  • You don't need to send the Content-Type header, since PHP does this for you.
  • You don't need to set the file executable - it only needs to be readable.

As an example, create ~/public_html/ #! /usr/bin/env python print "Content-type: text/html" print print "<html><body><h1>Hello, world!</h1></body></html>"

Then set it executable by running chmod u+x ~/public_html/

You should now be able to run over the web it via - substituting your own zID into the URL.

Requests for CGI scripts are automatically redirected from, and are actually run on

For better performance, point your links directly there to avoid the redirection process.

Do I have to use filename suffixes such as .pl or .cgi?

The CGI server uses the filename suffixes listed above to tell whether to run a file through CGI or serve the contents as-is.

If you want it to run a program without a suffix, there's two ways you can do it.

If you put it in your ~/public_html/cgi-bin directory, it will be run as a CGI script, whatever the filename.

Otherwise, you need to create or edit a file called .htaccess in the same directory as your script, and add the lines <Files "mycgiscript"> SetHandler application/x-setuid-cgi </Files>

(replacing mycgiscript with the relevant filename)

Make sure the .htaccess file is world-readable by running chmod o+r .htaccess

How do I stop a file being treated like a CGI script?

If you have a file that looks like a CGI script but you want to serve the contents as-is instead of running it, again add a section to .htaccess:

<Files ""> ForceType text/plain </files>

How do I access files outside of public_html??

You can't.

The CGI servers can only see files under /web/YourZID, which maps to your public_html directory.

This is to stop a rogue script from leaking or damaging files in your home directory itself.

Your scripts should access any files they need via this path, not via /home/YourZID/public_html/.

/web/YourZID is avaible on all CGS-Linux computers, so you can use and test your scripts from the command line without having to reconfigure them.

What about security?

For details on restricting web access to HTTPS, specific users / hosts / etc, see Restricting Web Access.

As for general security considerations:

  • CGI scripts should only be readable/executable by you and your group; never make them world-readable / writable / executable.
  • Never run commands based directly on input from the user; sanitise all input and assume malicious users are running your script at all times.
  • Never accept passwords or other senstitive information unencrypted; use HTTPS for this at all times.

Fixing Errors

Permission Problems

The most common CGI/PHP errors boil down to permissions issues.

Here are the minimum permissions needed in order for everything to work:

  • Static files (.html / .css / .png etc.) are served by the w3serv user, and so either need to be world-readble or group-readable by w3serv.
  • Any .htaccess files need to be readable by w3serv as well.
  • PHP and SHTML files need to be readable by the owner, but do not need to be executable.
  • CGI scripts must be executable by the owner.
  • Directories (and all their parents up to public_html) only need to be world-executable or group-executable by w3serv; they don't need to be readable.
  • CGI scripts need to be owned by the owner of the parent home directory.
    • This means that /home/someuser/public_html/cgi-bin/ must be owned by someuser - files owned by anyone else will not run.
    • For group-owned directories (such as class/project accounts), use the priv takeover command to change ownership of the files to the group.
    • If you use this command, ensure that the file is group-writable, or you will no longer be able to edit it.
    • The group must be a member of the GroupCGI class for priv takeover to work - contact System Support if it complains that this is missing.

Common Error Messages

Real UID could not be changed!

This is usually caused by process limits on the CGI servers.

We set limits on the number of simultaneous processes and the amount of CPU and RAM any one user can use on the CGI servers at any one time.

If running your script would exceed these limits, it won't run and the server will return this error instead.

This is usually due to a misbehaving script spinning out of control, or just failing to exit and so stacking up multiple copies of itself on the server.

You can use the priv cleancgi command to kill off any of your CGI processes running on the server and fix this.

(Of course, it would be good to then fix your script so it doesn't happen again...)

Script does not have same UID

This error means that the script is not owned by the owner of the home directory.

See Permission Problems above for help with this.

Malformed header from script

This means that your script did not send the required HTTP headers (at minimum, a Content-Type header and a blank line) before any other output.

It's often due to syntax errors in your script sending error messages instead of the content.

Your best bet is to turn on debugging mode (see below) to see the full text of the error so you can fix it.

Note that the CGI server redirects stderr to stdout, so if your code sends other output to stderr before sending the headers, it will trigger this error.

Turning on Debugging Mode

Users don't have access to the apache logs on our servers, so debugging your scripts requires a little extra work.

CGI scripts on our servers are handled by CGIwrap, which provides a setuid environment for CGI execution - and there's a debug version available.

To debug a script, set the handler for your script to be x-setuid-cgid.

To do this, add the following lines to an .htaccess file in the same directory:

<Files "problem_script.cgi"> SetHandler application/x-setuid-cgid </Files>

Next time you access the script, it will dump its full environment and output as text.

Last edited by jbc 18/07/2017

Tags for this page:

CGI, php, scripts, web, htaccess