やったことのメモ。
(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の残りを監視してアラート飛ばすのを作る予定。