我们有一个装有 apache 2.2.14、PHP 5.3.2 的网络服务器。
PHP 使用 mod_fcgid 执行(见底部)。一切正常,但有时,我们仍需弄清楚是什么触发了这种情况,当 php 进程“轮换”时,它们仍处于活动状态且处于孤立状态:apache 会产生新的 php 进程,而旧进程仍保留在系统中。终止它们并不总能将它们踢走。更有可能的是,“apache2ctl graceful”会将系统从这些过时的进程中释放出来。我们在错误日志中发现了这一点:[2013 年 6 月 18 日星期二 20:49:54] [警告] mod_fcgid:进程 2009 graceful kill 失败,根据我搜索的结果,发送 SIGKILL 是相当正常的,但这就是我在其中一个进程泄漏期间在 apache 日志中发现的全部内容。
幸运的是,这种情况很少发生,通常 apache 和 php 运行正常,在 fcgid 子代更新期间不会出现问题。我们如何了解这些情况下出了什么问题?
站点中的 mod_fcgid 配置:
<IfModule mod_fcgid.c>
SuexecUserGroup domain domain
<Directory /var/www/fomain.it/htdocs/>
AddHandler fcgid-script .php
FCGIWrapper /var/www/fcgi/domain.it/fcgi-starter-php .php
Options +ExecCGI -Indexes
AllowOverride FileInfo Options
Order allow,deny
Allow from all
</Directory>
<Directory /var/www/fcgi/domain.it/>
AllowOverride None
Options +ExecCGI MultiViews -Indexes
Order allow,deny
Allow from all
</Directory>
</IfModule>
/var/www/fcgi/domain.it/fcgi-starter-php:
#!/bin/sh
PHPRC=/var/www/fcgi/domain.it/php/
export PHPRC
PHP_FCGI_CHILDREN=8
export PHP_FCGI_CHILDREN
PHP_FCGI_MAX_REQUESTS=5000
export PHP_FCGI_MAX_REQUESTS
exec /usr/lib/cgi-bin/php $1
我们目前找到了一种避免服务器充满孤立进程的解决方法。您可以使用以下方法摆脱陈旧的进程:
apache2ctl graceful
并使用以下命令终止这些进程:
pkill -f -x /usr/lib/cgi-bin/php -P 1
编写脚本并安排这两个命令(经过适当的检查)将避免服务器承载大量无用的进程,但问题仍然存在。
答案1
我遇到了类似的问题,即 fcgid 在一段时间的活动之后用尽了可用的进程槽。
日志信息大致如下:
[fcgid:warn] mod_fcgid: can't apply process slot for /var/www/cgi-bin/xxx/php-cgi, referer: ...
我追踪问题到此为止:
[fcgid:emerg] (35)Resource deadlock avoided: [client ....] mod_fcgid: can't get pipe mutex, referer: ...
这是由于锁定不当造成的。在我的例子中,Apache 使用 fcntl() 锁定(在 Debian 上是默认的),因此我将其更改为 flock() apache2.conf
:
Mutex flock:${APACHE_LOCK_DIR} default
引导我找到解决方案的参考资料: https://bz.apache.org/bugzilla/show_bug.cgi?id=53999
关于各种锁定选项的文档(fcgid 有一个警告,建议不要将其用于涉及线程的任何操作): https://httpd.apache.org/docs/2.4/mod/core.html#mutex
答案2
我没有真正的答案,但也许更多的信息可以帮助解决问题。我想说的是,我在使用 PHP 5.3.5 的 Windows 服务器上遇到了同样的问题。
一些 cgi 进程在完成实际执行后仍保留为一种僵尸任务。它们甚至会忽略 max_execution time 等设置。
目前我有一个计划脚本可以终止这些旧进程。该解决方案的问题是,即使“正常”的 cgi 进程也被终止了,检测进程的运行时间并仅在它们的 max_execution 时间已过时才终止它们可能会很有用。
答案3
按照 Thomas 的建议改为“sem”https://bz.apache.org/bugzilla/show_bug.cgi?id=53999对我有用。
因此我建议任何人都编辑他的 apache2.conf,注释掉 Mutex 行,并输入:
# Mutex file:${APACHE_LOCK_DIR} default # Original debian config
Mutex sem # Solves orphaned PHP processes.