最後更新: 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