cgi-bin

最後更新: 2018-01-26

 

介紹

The server will set the CGI environment variables as described in the CGI specification

  • DOCUMENT_ROOT    # Set with the content of the related DocumentRoot directive.
  • SERVER_NAME         # The fully qualified domain name related to the request.

目錄

 


vhosts Setting

 

Centos7: mod_cgi.so

/etc/httpd/conf.modules.d/01-cgi.conf

<IfModule mpm_worker_module>
   LoadModule cgid_module modules/mod_cgid.so
</IfModule>
<IfModule mpm_event_module>
   LoadModule cgid_module modules/mod_cgid.so
</IfModule>
<IfModule mpm_prefork_module>
   LoadModule cgi_module modules/mod_cgi.so
</IfModule>

/etc/httpd/conf.modules.d/00-mpm.conf

LoadModule mpm_prefork_module modules/mod_mpm_prefork.so

/etc/httpd/conf.d/vhosts.conf

...

<Directory /home/vhosts/datahunter.org/public_html>
    AllowOverride All
    Require all granted
    AddHandler cgi-script .cgi
    Options +ExecCGI +Includes +MultiViews Includes FollowSymLinks
</Directory>

...

Remark

Any file that has the handler cgi-script will be treated as a CGI script

AddHandler / SetHandler directive

  CGI programs are often restricted to ScriptAlias'ed directories for security reasons.

  Arbitrary directories => "ExecCGI" must be specified in the Options directive

ScriptAlias directive

  Apache will assume that every file in this directory is a CGI program, and will attempt to execute it

ScriptAlias "/cgi-bin/" "/usr/local/apache2/cgi-bin/"

mime-type application/x-httpd-cgi

 


mod_cgid.so

 

mod_cgid 的好處

forking a process from a multi-threaded server is a very expensive operation

because the new process will replicate all the threads of the parent process.

mod_cgid creates an external daemon that is responsible for forking child processes to run CGI scripts.

mod_cgid identical in configuration and operation to mod_cgi.

( The only exception is the additional directive "ScriptSock"

which gives the name of the socket to use for communication with the cgi daemon.)

ScriptSock file-path

This directive sets the filename prefix of the socket to use for communication with the CGI daemon,

an extension corresponding to the process ID of the server will be appended.

# 當 Apache start 後

ls -al /var/run/httpd/

total 4
drwx--x---  3 root   apache 120 Oct 16 10:23 .
drwxr-xr-x 30 root   root   740 Oct 16 05:54 ..
srwx------  1 www    root     0 Oct 15 17:48 cgisock.24864
drwx------  2 apache apache  40 Aug  8 08:42 htcacheclean
-rw-r--r--  1 root   root     5 Oct 16 10:23 httpd.pid

 


Bash

 

testcgi.cgi

#!/bin/bash

echo "Content-type: text/html"
echo ""
echo '<html>'
echo '<head>'
echo '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">'
echo '<title>Hello World</title>'
echo '</head>'
echo '<body>'
echo 'Hello World'
echo '</body>'
echo '</html>'

# 非必要
exit 0

Remark

[1] permission 要有 x

chmod o+x testcgi.cgi

[2] output (echo) 要有特定 format, 不可以亂 output 東西

[Time] [cgi:error] [pid 32232] [client c.c.c.c:n] malformed header from script 'testcgi.cgi': Bad header: test cgi

 


Perl

 

#!/usr/bin/perl

\n\r (CR+LF)

 


Thread & Process

 

pstree | grep httpd

|-httpd-+-httpd---tim.cgi---sleep
|       `-4*[httpd---63*[{httpd}]]

 


CGI timeout

 

Timeout

Amount of time the server will wait for certain events before failing a request

mod_cgi and mod_cgid 都用得此設定

Default: TimeOut 60

它還會影響

 - When reading data from the client
 - When writing data to the client
 - mod_cgi and mod_cgid
 - mod_ext_filter
 - mod_proxy

CGIDScriptTimeout Directive // mod_cgid 才有此設定

可以在 server config, virtual host, directory, .htaccess 設定

# If the time is exceeded, the request and CGI are terminated.

# Default: value of Timeout directive when unset

 

# 完全無 output 時 timeout

i.e.

#!/bin/bash

sleep 20
echo "Content-type: text/html"
echo ""
echo '<html>'
echo '<head>'
echo '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">'
echo '<title>Hello World</title>'
echo '</head>'
echo '<body>'
echo 'Hello World'
echo '</body>'
echo '</html>'

exit 0

Browser Display

Gateway Timeout
The gateway did not receive a timely response from the upstream server or application.

Log   

..  [cgid:error] [pid 3797:tid N] [client r.r.r.r:n] Script timed out before returning headers: test.cgi

行到一半時 timeout

Browser Display

只 output 部分內容

Log

..  [core:error] [pid 4011:tid N] (70007)The timeout specified has expired: [client r.r.r.r:n] AH00574:
    ap_content_length_filter: apr_bucket_read() failed

 


Troubleshoot

 

由 mod_cgi 轉用 mod_cgid 後

... (13)Permission denied: [client x.x.x.x:50392] AH01257: unable to connect to cgi daemon after multiple tries: 
    /home/vhosts/xxx/public_html/tim.cgi, referer: https://xxx/

[fix]

因為 /var/run/httpd/cgisock.N 的 permission 係 700, www.root

# Centos
User apache
Group apache