mod_fcgid

最後更新: 2018-01-18

介紹

 

HomePage: https://wiki.apache.org/httpd/php-fcgid

 * execute PHP scripts with the permissions of their owners instead of the Apache user.

 * starts CGI program instances and these programs remain running to handle further incoming requests.

mod_php 的缺點:

* mod_php will be loaded into httpd's memory even when serving static pages
* mod_php forces you to load prefork (or worker)MPM

mod_fcgi Benefits:

* PHP runs into a separated process
* binary compatible alternative to mod_fastcgi.
* official Apache module

它與 suPHP 有極類似的功能

 


安裝

 

yum install mod_fcgid php-cli

把原來 Apache 的 php.conf backup 起佢

原來的 php.conf 內容:

# Centos6 Config
<IfModule prefork.c>
  LoadModule php5_module modules/libphp5.so
</IfModule>
<IfModule worker.c>
  LoadModule php5_module modules/libphp5-zts.so
</IfModule>

AddHandler php5-script .php
AddType text/html .php

DirectoryIndex index.php

AddType application/x-httpd-php-source .phps

 


/etc/php.ini

 

;Default is 1
cgi.fix_pathinfo = 1

cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. 

PHP's previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME,

and to not grok what PATH_INFO is.  For more information on PATH_INFO, see the cgi specs. 

Setting this to 1 will cause PHP CGI to fix its paths to conform to the spec. 

A setting of zero causes PHP to behave as before.

You should fix your scripts to use SCRIPT_FILENAME rather than PATH_TRANSLATED.

http://www.php.net/manual/en/ini.core.php#ini.cgi.fix-pathinfo

 


fcgid.conf

 

Debian

/etc/apache2/mods-enabled/fcgid.conf

<IfModule mod_fcgid.c>
  AddHandler    fcgid-script .fcgi
  FcgidConnectTimeout 20
</IfModule>

Centos6

/etc/httpd/conf.d/fcgid.conf

# 本身有的設定

LoadModule fcgid_module modules/mod_fcgid.so

AddHandler fcgid-script fcg fcgi fpl

# directory for AF_UNIX sockets to communicate with FastCGI applications
FcgidIPCDir /var/run/mod_fcgid

# shared memory on Unix to maintain state which is shared between httpd processes.
FcgidProcessTableFile /var/run/mod_fcgid/fcgid_shm

# 追加 Setting, 令整 Server 行 CGI

# 可以在 Context: server config, virtual host, directory, .htaccess
# 用 fcgi 去行 php
AddHandler   fcgid-script     .php
# FcgidWrapper command [ suffix ]
# suffix argument restricts the use of this FCGI server to all URLs
# A suffix needs to start with '.'
FcgidWrapper /usr/bin/php-cgi .php

# 在 php.ini 的 cgi.fix_pathinfo=1 時, 這裡都要 1
# allows PHP to provide additional path information "SCRIPT_NAME"
FcgidFixPathinfo 1

# Basic Setting
AddType text/html .php
AddType application/x-httpd-php-source .phps
DirectoryIndex index.php index.html index.htm

# 所有地方都行到 CGI
<Location />
    # Allow execution of CGI scripts.
    Options +ExecCGI
</Location>

 


Checking

 

在 <?php phpinfo ?> 的顯示:

Server API     Apache 2.0 Handler

變成了

Server API: CGI/FastCGI

 


Apache per VirtualHost 設定

 

在 /etc/httpd/conf.d 內由於 php.conf 比 fcgid.conf 排後,

所以 Default 所有Website 都是用 mod_php 的

如果要個別 host 用 mod_fcgid, 那只需要在 vhost 內加以以下兩句

vhosts.conf

<VirtualHost *:80>
    <Directory ... >
        ...
        Options +ExecCGI ...
    </Directory>
    # fcgid
    AddHandler fcgid-script .php
    FcgidWrapper /usr/bin/php-cgi .php
</VirtualHost>

php.conf

<FilesMatch \.php$>
    SetHandler application/x-httpd-php
</FilesMatch>

To

AddHandler php5-script .php

 


fcgid.conf 進階設定

 

Timeout value

# Default: 3
# trying to connect to a FastCGI application
FcgidConnectTimeout          2

# trying to read from or write to a FastCGI application.
# 當 Over 了 40 秒後, Server 會見到以下的 log
# [Fri Jul 11 10:23:23 2014] [warn] [client x.x.x.x] mod_fcgid: read data timeout in 40 seconds
# [Fri Jul 11 10:23:23 2014] [error] [client x.x.x.x] Premature end of script headers: index.php
# 此 setting 相當於 "max_execution_time" 及 "max_input_time"
FcgidIOTimeout              40

# maximum time limit for request handling
# The purpose of this directive is to terminate hung applications.
FcgidBusyTimeout            300

Processes Management

# 同時有多少個 php-cgi 在行
# Default: 1000 ?!
FcgidMaxProcesses           10

# Maximum requests a process handles before it is terminated
MaxRequestsPerProcess       1000

# Idle application processes which have existed for greater than this time will be terminated
# 每 FcgidIdleScanInterval(120) 查看一次有沒有 Idle proccess
FcgidProcessLifeTime        3600

# Number of seconds of idle time before a process is terminated
# Proccess 數量大於 FcgidMinProcessesPerClass 才觸發
FcgidIdleTimeout            240

######################################## ProcessesPerClass

# number of processes that will be retained in a process class after finishing requests
FcgidMinProcessesPerClass 3
FcgidMaxProcessesPerClass 100

Process Class

A process class is the set of processes

 which were started with the same executable file and

 share certain other characteristics such as virtual host and identity

Buffer

# Default: 65536   <-- 64k
# 當 request body 超過這數後, 其餘的會保存在 temporary file.
FcgidMaxRequestInMem 65536

# response data the module will read from the FastCGI application before flushing the data to the client.
FcgidOutputBufferSize 65536

Upload File

# body exceeds this amount => 500 Server Error
# Default: 131072 bytes        <-- 128 kbyte
# MaxRequestLen <-- 舊名稱
# unit bytes, 10485760 = 10 Mbyte
FcgidMaxRequestLen 10485760

 

 


Wrapper script

 

Used by mod_fcgid to launch php-cgi processes.

Usage:

FcgidWrapper command [ suffix ]

* command: The given command is used to spawn FCGI server processes.

* suffix:  argument restricts the use of this FCGI server to all URLs with the given exact path suffix.

i.e.

FcgidWrapper /home/vhosts/fcgid/mywebsite-wrapper

chmod +x mywebsite-wrapper

File: /home/vhosts/fcgid/website-wrapper

# wrapper script to invoke PHP
# Set desired PHP_FCGI_* environment variables.
# PHP FastCGI processes exit after 1000 requests by default.
# When that occurs, an error will be logged and 500 Internal Server Error will be returned to the client.

PHP_FCGI_MAX_REQUESTS=1000
export PHP_FCGI_MAX_REQUESTS

exec /usr/bin/php-cgi

 


FcgidCmdOptions

 

# options to be specified for a specific command spawned by mod_fcgid.
# server config, virtual host

Syntax:    FcgidCmdOptions command option [option]

* Multiple environment variables are defined by repeating the InitialEnv option.

Example:

# mod_fcgid will terminate it after it(wrapper) has handled 2000 requests

FcgidCmdOptions /usr/local/bin/wrapper \
InitialEnv MAX_REQUESTS=2000 \
MaxRequestsPerProcess 2000 \
IOTimeout 90
  • ConnectTimeout seconds
  • IdleTimeout seconds
  • IOTimeout seconds
  • MaxProcesses value
  • MaxProcessLifeTime seconds
  • MaxRequestsPerProcess value
  • MinProcesses value

 


Testing result

 

apache:

 

 

apache + xcache:

 

 

mod_fcgid:

 


Troubleshoot

 

<1>

Page Forbidden

解決

Options .... FollowSymLinks ....

<2>

Invalid command 'php_admin_value', perhaps misspelled or 
defined by a module not included in the server configuration
Action 'configtest' failed.

 


PHP 使用 HTTP_AUTHORIZATION Login

 

在 Server API: CGI/FastCGI 情況下使用它 # phpinfo

實現

Assign the username/pass pairs to an environment variable named HTTP_AUTHORIZATION

To setting an HTTP_AUTHORIZATION environment variable to the value of the Authorization HTTP request header

在 .htaccess 內加入

<IfModule mod_fcgid.c>
    # Checking if the HTTP Authorization header exists and has a value
    RewriteCond %{HTTP:Authorization} .
    # .* is a regular expression that matches any request. 
    # The - means that the URL should not be changed.
    # Sets an environment variable HTTP_AUTHORIZATION with the value of the HTTP Authorization header
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
</IfModule>

Test Code

<?php
    if (!isset($_SERVER['PHP_AUTH_USER'])) {
        header('WWW-Authenticate: Basic realm="My Realm"');
        header('HTTP/1.0 401 Unauthorized');
        echo 'Text to send if user hits Cancel button';
        exit;
    } else {
        echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
        echo "<p>You entered {$_SERVER['PHP_AUTH_PW']} as your password.</p>";
    }
?>

 


PHP_FCGI_CHILDREN

 

PHP child process management (PHP_FCGI_CHILDREN) should always be disabled with mod_fcgid,

which will only route one request at a time to application processes it has spawned;

thus, any child processes created by PHP will not be used effectively. (Additionally, the PHP child processes may not be terminated properly.)

By default, and with the environment variable setting PHP_FCGI_CHILDREN=0, PHP child process management is disabled.

 


phpmyadmin 的設定

 

Alias /phpmyadmin /usr/share/phpMyAdmin

ScriptAlias

ScriptAlias /cgi-bin/ /web/cgi-bin/

相當於

Alias /cgi-bin/ /web/cgi-bin/
<Location /cgi-bin >
    SetHandler cgi-script
    Options +ExecCGI
</Location>

<Directory /usr/share/phpMyAdmin/>
    Options +ExecCGI
    Deny from All
    Allow from 127.0.0.1
</Directory>

/etc/phpMyAdmin/config.inc.php

// Authentication method (config, http or cookie based)?
$cfg['Servers'][$i]['auth_type'] = 'http';

cookie:

When using the cookie authentication (the default), the mcrypt extension is strongly suggested.

supports a wide variety of block algorithms such as DES

# pass authentication variable to CGI using following rewrite rule:

RewriteEngine On
# 當有其他 rule 時, 不要加 ",L" !!
RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization}]

config:

<IfModule mod_fcgid.c>
    RewriteEngine On
    RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization}]
        <Directory /usr/share/phpMyAdmin/>
            Options +ExecCGI
            Deny from All
            Allow from 127.0.0.1
        </Directory>
</IfModule>

P.S.

Server-Variables: These are variables of the form %{ NAME_OF_VARIABLE }


php-cgi 的 php.ini

 

link: http://datahunter.org/php.ini#php-cgi_php.ini

 


event apache

 

init───apache2─┬─apache2───2*[php-cgi]
               ├─apache2───65*[{apache2}]
               └─apache2───17*[{apache2}]

 


Doc

 

http://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html

 

 

Creative Commons license icon Creative Commons license icon