CGI Scripting with Tengine

What's the big deal? All Web servers support CGI scripts, right? NO! Nginx and Tengine don't. Why? Well, because it's a horribly inefficient protocol. For every request, the web server must fire up a large external interpretter, the interpretter loads a script, the script is parsed, compiled, executed, and finally output is sent back to the web-server. Other systems reduce this to just sending the URL over a UNIX-domain socket to an interpretter that is already running and has likely already parsed and compiled the scripts. This is a huge benefit.

BUT! ... My php-fpm server only understands PHP. Its incredibly fast an efficient, but what if you have that one and only perl script or (shudder) a bash script? I would NOT recommend this hack on a production server due to security concerns. (Generally, don't use bash for CGI processing. Its a good hammer, but CGI isn't a nail.) But... here's one way to do it!

First a bit of magic in your server { } section of your web server config file :

location ~ ^/cgi-bin(.*)$ { gzip off; include /etc/tengine/fastcgi.conf; fastcgi_split_path_info ^/cgi-bin/(.*cgi)(.*)$; fastcgi_param CGI_FILENAME $fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $document_root/cgi-bin.php; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; }

Now, you need a wrapper called cgi-bin.php (in server root):

<?php $scriptname = "{$_SERVER['DOCUMENT_ROOT']}/cgi-bin/{$_SERVER['SCRIPT_NAME']}"; if (array_key_exists('HTTP_REFERER',$_SERVER)) { putenv ("HTTP_REFERER={$_SERVER['HTTP_REFERER']}"); } putenv("DOCUMENT_ROOT={$_SERVER['DOCUMENT_ROOT']}"); putenv("QUERY_STRING={$_SERVER['QUERY_STRING']}"); putenv("REMOTE_ADDR={$_SERVER['REMOTE_ADDR']}"); putenv("REMOTE_PORT={$_SERVER['REMOTE_PORT']}"); if (array_key_exists('REMOTE_USER',$_SERVER)) { putenv("REMOTE_USER={$_SERVER['REMOTE_USER']}"); } putenv("REQUEST_METHOD={$_SERVER['REQUEST_METHOD']}"); putenv("REQUEST_URI={$_SERVER['REQUEST_URI']}"); putenv("SCRIPT_FILENAME=$scriptname"); putenv("SCRIPT_NAME={$_SERVER['SCRIPT_NAME']}"); if (array_key_exists('PATH_INFO',$_SERVER)) { putenv("PATH_INFO={$_SERVER['PATH_INFO']}"); } $output = shell_exec ($scriptname); echo preg_replace('/^.+\n/', '', $output); ?>

Now, assuming you have a /cgi-bin directory, you can run scripts like /cgi-bin/mycgi.cgi?h=45&y=6 or whatever. The script must be executable and must end in cgi and must be in the /cgi-bin directory.