一、進程跟蹤
| 代碼如下 |
複製代碼 |
# top //找出CPU使用率高的進程PID # strace -p PID //跟蹤進程 # ll /proc/PID/fd //查看該進程在處理哪些檔案
|
將有可疑的PHP代碼修改之,如:file_get_contents沒有設定逾時時間。
二、記憶體配置
如果進程跟蹤無法找到問題所在,再從系統方面找原因,會不會有可能記憶體不夠用?據說一個較為乾淨的PHP-CGI開啟大概20M-30M左右的記憶體,決定於PHP模組開啟多少。
通過pmap指令查看PHP-CGI進程的記憶體使用量情況
# pmap $(pgrep php-cgi |head -1)
按輸出的結果,結合系統的記憶體大小,配置PHP-CGI的進程數(max_children)。
三、監控
最後,還可以通過監控與自動回復的指令碼保證服務的正常運轉。下面是我用到的一些指令碼:
只要一個php-cgi進程佔用的記憶體超過 %1 就把它kill掉
| 代碼如下 |
複製代碼 |
#!/bin/sh PIDS=`ps aux|grep php-cgi|grep -v grep|awk’{if($4>=1)print $2}’` for PID in $PIDS do echo `date +%F….%T`>>/data/logs/phpkill.log echo $PID >> /data/logs/phpkill.log kill -9 $PID done |
檢測php-fpm進程
| 代碼如下 |
複製代碼 |
#!/bin/bash netstat -tnlp | grep “php-cgi” >> /dev/null #2&> /data/logs/php_fasle.log if [ "$?" -eq "1" ];then #&& [ `netstat -tnlp | grep 9000 | awk '{ print $4}' | awk -F ":" '{print $2}'` -eq "1" ];then /usr/local/webserver/php/sbin/php-fpm start echo `date +%F….%T` “System memory OOM.Kill php-cgi. php-fpm service start. ” >> /data/logs/php_monitor.log fi |
通過http檢測php執行
| 代碼如下 |
複製代碼 |
#!/bin/bash status=`curl -s –head “http://127.0.0.1:8080/chk.php” | awk ‘/HTTP/ {print $2}’` if [ $status != "200" -a $status != "304" ]; then /usr/local/webserver/php/sbin/php-fpm restart echo `date +%F….%T` “php-fpm service restart” >> /data/logs/php_monitor.log fi |
解決方案二
如果你常用上面複雜我們可以按下步驟來監控與重啟PHP-FPM來解決此問題
PHP-FPM啟動指令碼/etc/init.d/php-fpm
從PHP 5.3.3開始就已經整合了PHP-FPM所以php-fpm在PHP 5.3.2以後的版本不支援以前的php-fpm (start|restart|stop|reload) 了,不用專門再打補丁了,只需要解開源碼直接configure,關於php-fpm的編譯參數有
| 代碼如下 |
複製代碼 |
--enable-fpm --with-fpm-user=www --with-fpm-group=www --with-libevent-dir=libevent |
位置
進入到php原始碼目錄下,然後:
| 代碼如下 |
複製代碼 |
cp -f (php -5.3.x-source-dir)/sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm |
| 代碼如下 |
複製代碼 |
#! /bin/sh ### BEGIN INIT INFO # Provides: php-fpm # Required-Start: $remote_fs $network # Required-Stop: $remote_fs $network # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: starts php-fpm # Description: starts the PHP FastCGI Process Manager daemon ### END INIT INFO prefix=/usr/local/php exec_prefix=${prefix} php_fpm_BIN=${exec_prefix}/sbin/php-fpm php_fpm_CONF=${prefix}/etc/php-fpm.conf php_fpm_PID=${prefix}/var/run/php-fpm.pid php_opts="--fpm-config $php_fpm_CONF" wait_for_pid () { try=0 while test $try -lt 35 ; do case "$1" in 'created') if [ -f "$2" ] ; then try='' break fi ;; 'removed') if [ ! -f "$2" ] ; then try='' break fi ;; esac echo -n . try=`expr $try + 1` sleep 1 done } case "$1" in start) echo -n "Starting php-fpm " $php_fpm_BIN $php_opts if [ "$?" != 0 ] ; then echo " failed" exit 1 fi wait_for_pid created $php_fpm_PID if [ -n "$try" ] ; then echo " failed" exit 1 else echo " done" fi ;; stop) echo -n "Gracefully shutting down php-fpm " if [ ! -r $php_fpm_PID ] ; then echo "warning, no pid file found - php-fpm is not running ?" exit 1 fi kill -QUIT `cat $php_fpm_PID` wait_for_pid removed $php_fpm_PID if [ -n "$try" ] ; then echo " failed. Use force-quit" exit 1 else echo " done" fi ;; force-quit) echo -n "Terminating php-fpm " if [ ! -r $php_fpm_PID ] ; then echo "warning, no pid file found - php-fpm is not running ?" exit 1 fi kill -TERM `cat $php_fpm_PID` wait_for_pid removed $php_fpm_PID if [ -n "$try" ] ; then echo " failed" exit 1 else echo " done" fi ;; restart) $0 stop $0 start ;; reload) echo -n "Reload service php-fpm " if [ ! -r $php_fpm_PID ] ; then echo "warning, no pid file found - php-fpm is not running ?" exit 1 fi kill -USR2 `cat $php_fpm_PID` echo " done" ;; *) echo "Usage: $0 {start|stop|force-quit|restart|reload}" exit 1 ;; esac |
編輯好後儲存,執行以下命令
| 代碼如下 |
複製代碼 |
chmod +x /etc/init.d/php-fpm chkconfig php-fpm on # 檢查一下 chkconfig --list php-fpm php-fpm 0:off 1:off 2:on 3:on 4:on 5:on 6:off |
完成!可以使用以下命令管理php-fpm了
| 代碼如下 |
複製代碼 |
service php-fpm start service php-fpm stop service php-fpm restart service php-fpm reload /etc/init.d/php-fpm start /etc/init.d/php-fpm stop /etc/init.d/php-fpm restart /etc/init.d/php-fpm reload |
運行service php-fpm start提示出錯,怎麼都沒找到問題所在,後來才知道要把php-fpm.conf裡的PID路徑前的:分號刪掉!