やったことのメモ。
(12)Cannot allocate memory: fork: Unable to fork new process
が発生したので調査のためにスクリプトを追加。
発生までの経緯をみるとどうもswapが徐々に喰いつぶされていき、swapが無くなると
上記のエラーが発生しているような感じ。
徐々にといっても何らかのタイミングでガクンとswapが減るのでそれをどうにか
突き止めたい。。。
いろいろ調べて以下のページを参考にしてスクリプトを作成(そのまま)
Find Out What Is Using Your Swap
http://northernmost.org/blog/find-out-what-is-using-your-swap/
/proc/以下のプロセスのフォルダ内のsmaps内をさらって合計していく感じ。
■getswap.sh
#!/bin/bash # Get current swap usage for all running processes # Erik Ljungstrom 27/05/2011 SUM=0 OVERALL=0 for DIR in `find /proc/ -maxdepth 1 -type d | egrep "^/proc/[0-9]"` ; do PID=`echo $DIR | cut -d / -f 3` PROGNAME=`ps -p $PID -o comm --no-headers` for SWAP in `grep Swap $DIR/smaps 2>/dev/null| awk '{ print $2 }'` do let SUM=$SUM+$SWAP done echo "PID=$PID - Swap used: $SUM - ($PROGNAME )" let OVERALL=$OVERALL+$SUM SUM=0 done echo "Overall swap used: $OVERALL"
■cronswap.sh
クーロンで叩く用。
#!/bin/bash FILENAME=`date +"%Y%m%d_%H%M%S"` echo "${FILENAME}" /root/swapLog/getswap.sh | egrep -v "Swap used: 0" |sort -n -k 5 > /root/swapLog/log/"${FILENAME}".log
■logs
このフォルダに日時の形式で出力
■cronの設定
1ファイル2KB程度なのでとりあえずとりっぱなしで。10分毎。
#swaplog */10 * * * * /root/swapLog/cronswap.sh
■設置時のswap出力例
swapを使ってるプロセスが表示される。
$ less 20150914_162958.log Overall swap used: 123388 PID=1840 - Swap used: 28 - (syslogd ) PID=2245 - Swap used: 28 - (saslauthd ) PID=2247 - Swap used: 28 - (saslauthd ) PID=2248 - Swap used: 28 - (saslauthd ) PID=2244 - Swap used: 32 - (saslauthd ) PID=2246 - Swap used: 32 - (saslauthd ) PID=1843 - Swap used: 44 - (klogd ) PID=2328 - Swap used: 48 - (mingetty ) PID=2323 - Swap used: 52 - (mingetty ) PID=2332 - Swap used: 52 - (mingetty ) PID=2307 - Swap used: 56 - (gam_server ) PID=2324 - Swap used: 56 - (mingetty ) PID=2330 - Swap used: 56 - (mingetty ) PID=2329 - Swap used: 60 - (mingetty ) PID=1 - Swap used: 64 - (init ) ・・・・ PID=2274 - Swap used: 148 - (hald-runner ) PID=9940 - Swap used: 148 - (pop3-login ) PID=2054 - Swap used: 152 - (mysqld_safe ) PID=2017 - Swap used: 224 - (vsftpd ) PID=496 - Swap used: 260 - (udevd ) PID=1962 - Swap used: 304 - (sshd ) PID=1901 - Swap used: 448 - (3dm2 ) PID=1914 - Swap used: 448 - (3dm2 ) PID=1915 - Swap used: 448 - (3dm2 ) PID=2273 - Swap used: 1900 - (hald ) PID=2320 - Swap used: 7172 - (miniserv.pl ) PID=1804 - Swap used: 7468 - (miniserv.pl ) PID=17177 - Swap used: 7736 - (spamd ) PID=17197 - Swap used: 8364 - (spamd ) PID=2303 - Swap used: 10060 - (yum-updatesd ) PID=2158 - Swap used: 24512 - (spamd ) PID=2101 - Swap used: 44588 - (mysqld )
あと合わせてsarコマンドも設定
参考
http://blog.ybbo.net/2013/07/10/oom-killer%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/
http://b.l0g.jp/dev/finding-bottleneck-with-sar1/
http://b.l0g.jp/dev/finding-bottleneck-with-sar2/
pstreeも確認するようにする。
$ pstree -lcph
http://itpro.nikkeibp.co.jp/article/COLUMN/20071204/288730/
またアクセスログの記録と対応するようにApacheのaccess_logの先頭にPIDを表示するように設定を変更した。
「%P」はPIDを出力する。先頭に追加。
これでswapを確保したままになっているのがhttpのプロセスだった場合にどのアクセスと対応しているのか
がわかるはず。
$ diff httpd.conf httpd.conf_back20150914 485,486c485,486 < LogFormat "%P %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined < LogFormat "%P %h %l %u %t \"%r\" %>s %b" common --- > LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined > LogFormat "%h %l %u %t \"%r\" %>s %b" common
再起動必須。
実際「Cannot allocate memory」が出て已む無くapacheをリスタートしようと
したのに起動に失敗したときの対応は以下。
#service httpd restart 失敗した! #/usr/sbin/lsof -i | grep http 開いているファイルのプロセスを特定 #kill-9 プロセスID そのほかのプロセスも殺す。 #service httpd start
後はswapの残りを監視してアラート飛ばすのを作る予定。