FastCGI
Please note that the approach described on this page is not recommended for new users. Our hosting accounts now use PHP-FPM for PHP scripts, which negates the need for FastCGI, and we provide support for WSGI for hosting Python applications.
FastCGI is an alternative to CGI which overcomes its performance problems. Rather than invoking a script or program once for each web request, FastCGI maintains persistent "server" processes which can handle numerous requests. The web server communicates with these processes over TCP or UNIX-domain sockets using an open protocol. Unlike mod_perl, mod_python, etc., which run user code inside the webserver, FastCGI keeps users' code separate, which is more secure and reliable. Most scripting languages have support for FastCGI, and present it with the same interface as regular CGI. You can use FastCGI for hosting dynamic content with Mythic Beasts shell accounts, but we recommend that you don't unless it's absolutely necessary, since doing so requires additional setup and can make debugging problems harder. Unless your site really is very busy, we're likely to respond to support requests about FastCGI by recommending that you use normal CGI instead.
To use FastCGI, you need to arrange for the webserver to run your scripts as
FastCGI server processes. It is easiest to do this with a .htaccess
file. If you want a whole directory of scripts to be invoked as FastCGI servers,
then use something like this:
Options +ExecCGI SetHandler fastcgi-script
Or, to run only scripts with a certain suffix - e.g., .fcgi
- as
FastCGI servers, use:
Options +ExecCGI AddHandler fastcgi-script .fcgi
Examples
Here are some trivial examples of scripts adapted for use under FastCGI. In each case, the modified version of the script will work either as a CGI or a FastCGI script:
Perl: the standard distribution contains the CGI::Fast module, which has an interface very similar to that for standard CGI. The changes are mostly trivial:
CGI | FastCGI |
---|---|
#!/usr/bin/perl -w use strict; use CGI; my $q = new CGI(); print $q->header(), $q->start_html('Test CGI script'), $q->p('Hello! The time is', scalar(localtime(time())), 'and your IP address is', $q->remote_addr(), $q->end_html(); |
#!/usr/bin/perl -w use strict; use CGI; use CGI::Fast; while (my $q = new CGI::Fast()) { print $q->header(), $q->start_html('Test CGI script'), $q->p('Hello! The time is', scalar(localtime(time())), 'and your IP address is', $q->remote_addr(), $q->end_html(); } |
Python: there are several modules for FastCGI support. We've installed fcgi.py from Total Control Software (no longer supported, but works fine). You can use any of the others if you install it in your own home directory. There are more changes than in the perl case, but the script is basically the same, and the new one still works under normal CGI:
#!/usr/bin/python import cgi import os import time print '''Content-Type: text/html <html><head><title> Test CGI Script </title></head><body> <p>Hello! The time is''' print time.asctime(), 'and your IP address is', print environ['REMOTE_ADDR'], '</body><html>' |
#!/usr/bin/python import fcgi import os import time while fcgi.isFCGI(): request = fcgi.Accept() request.out.write('''Content-Type: text/html <html><head><title> Test CGI Script </title></head><body> <p>Hello! The time is''') request.out.write(time.asctime(), 'and your IP address is') request.out.write(request.env['REMOTE_ADDR'], '</body><html>') request.Finish() |
C/C++: generally there's no need to write web applications
in C or C++, and we recommend that you don't; but sometimes it's useful (for
instance if you need to generate images on-demand or something similar where
scripting languages just aren't fast enough). Conversion to FastCGI operation
is trivial; you just need to make the changes below and compile your code with
-lfcgi
:
#include <stdio.h> #include <time.h> int main(void) { struct tm *t; time_t T; time(&T); t = localtime(&T); printf("<html><head><title>" "Test CGI Script" "</title></head><body>" "<p>Hello! The time is %s, " "and your IP address is %s.</p>" "</body></html>", asctime(t), getenv("REMOTE_ADDR")); } |
#include <fcgi_stdio.h> #include <time.h> int main(void) { struct tm *t; time_t T; while (FCGI_Accept() >= 0) { time(&T); t = localtime(&T); printf("<html><head><title>" "Test CGI Script" "</title></head><body>" "<p>Hello! The time is %s, " "and your IP address is %s.</p>" "</body></html>", asctime(t), getenv("REMOTE_ADDR")); } } |
Problems
The most serious problem with writing and using FastCGI programs is debugging
them. As with a normal CGI program, you can log diagnostics to the server error
log; since FastCGI programs run for extended periods of time, you may also be
able to use an interactive debugger to study the behaviour of your program.
Against this is the problem that, unlike regular CGI programs, any changes you
make won't immediately take effect, unless you arrange the accept loop in your
program to re-exec itself whenever it detects that the script file has changed
on disk. If you don't do that, you'll need to terminate your script (using the
kill
or killall
commands) and let the webserver
restart the new copy. But if you do this too often, or if your script dies of
its own accord, the webserver will conclude that it's not working properly and
hold off restarting it for a while.
So, you should set up a test environment for development (this is good advice in any case), and do the initial work on your scripts under a CGI environment rather than FastCGI.
For more advice, take a look at the resources on the FastCGI home page.