我今天重启了 apache 守护进程来重新加载配置文件,但之后我开始在系统上看到许多 php 僵尸进程。数量从 10 到 30 不等,它们在死机时都会占用一小部分 CPU。我应该从哪里开始调试这个问题?
我所做的修改是将每个子级的最大请求数从 0(大量内存泄漏)减少到 1000。我认为 php 进程来自从“哑”设备接收数据的脚本,即它们发送带有 GET 参数的请求而不关心结果。
一些数据:
uname -a
# uname -a
Linux <hostname> 2.6.32-71.29.1.el6.x86_64 #1 SMP Mon Jun 27 19:49:27 BST 2011 x86_64 x86_64 x86_64 GNU/Linux
ps -aux | php 命令
# ps aux | grep php
user1 5709 1.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5717 1.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5721 1.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5722 2.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5723 2.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5724 2.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5725 2.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5729 2.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5731 2.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5737 2.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5760 2.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5778 1.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5793 2.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5798 1.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5800 1.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5833 2.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5850 2.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5870 3.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5875 2.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5876 2.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5877 2.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5886 0.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5926 0.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5939 0.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5941 0.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5961 0.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5962 0.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5973 0.0 0.0 0 0 ? Z 12:15 0:00 [php] <defunct>
user1 5977 0.0 0.2 106836 8680 ? R 12:15 0:00 /usr/bin/php /home/user1/public_html/<script>.php
root 5981 0.0 0.0 103228 836 pts/0 S+ 12:15 0:00 grep php
自由的
# free -m
total used free shared buffers cached
Mem: 3831 3173 658 0 183 2502
-/+ buffers/cache: 487 3344
Swap: 4031 7 4024
正常运行时间
# uptime
12:18:10 up 105 days, 23:21, 1 user, load average: 0.23, 0.20, 0.18
还需要什么来帮助我调试这个吗?
答案1
这不是问题。僵尸进程不会占用 CPU、内存或进程表槽以外的任何东西。您说过,僵尸进程不会停留很长时间,所以 Apache 主进程所做的只是等待子进程退出,所以有时需要一段时间才能收割终止的子进程。
答案2
僵尸进程只是一个其父进程已经死亡/被杀死,并且还没有被清理的进程。
如果在服务重启期间发生这种情况,则完全正常。您应该阅读有关 Linux 进程状态的信息,大致信息如下:
- 运行:这是进程正在运行或准备运行的状态。
- 可中断:此状态是进程的阻塞状态,等待来自另一个进程的事件或信号
- 不可中断:也是阻塞状态。进程因某种原因被迫停止,例如等待硬件状态或无法处理信号。
- 已停止:一旦进程完成,就会出现此状态。此进程可以重新启动
- 僵尸:在此状态下,进程将被终止,但是信息仍然保留在进程表中。
然而,如果在您正常使用 Web 服务器时发生了这种情况(毕竟,我们谈论的是 php 进程),您可能会每分钟使用 cronjob 执行一次 apache 平稳重启(service apache2 reload
)来暂时修复这个问题,但这并不能解决蚕食您的可用插槽的根本问题。
在第二种情况下,您需要辨别哪个托管导致了僵尸,并且必须修复应用程序。99%的此类僵尸都是由编程不良的网站引起的。
答案3
请在使用 pcntl_fork() 分叉进程后添加代码 pcntl_wait()
$pid = pcntl_wait($status, WNOHANG);
int pcntl_wait ( int &$status [, int $options ] )
该wait
函数暂停当前进程的执行,直到子进程退出,或直到发出信号,其作用是终止当前进程或调用信号处理函数。如果在调用时子进程已经退出(即所谓的“僵尸”进程),则该函数立即返回。子进程使用的所有系统资源都将被释放