CPU使用率を検出してアラート(2)

前回、vmstatの1回目の値が正確な値ではないと書いていましたがLinuxでも同じなので調べてみたら前回実行からの平均値だろうです。単なる無知でしたorz。さらに1秒間隔では瞬間的なバッチ処理でアラート出してしまうので最低5秒間の平均をとるように変えました。その他ログ書き出しや例外処理を追加

実装に向けてLinux対応をしてみましたが移植の際に注意するのはこのスクリプトで使用しているコマンドのパスやオプションそしてvmstatの出力フォーマットをチェックすることですね。

#!/bin/sh

TO=webmaster@exsample.com
CC=user1@exsample.com
DATE=`date ‘+%Y-%m-%d’ `
TIME=`date ‘+%H%M%S’ `
DATETIME=`date ‘+%Y-%m-%d %T’ `
HOST=`hostname -i`
BORDER=70
LIMIT=95
IDLE=`/usr/bin/vmstat 5 2 | /usr/bin/tail -1 | /bin/awk ‘{print$15}’`
LOAD=`expr 100 – $IDLE`
LOGDIR=~/logs

if [ $# -eq 1 ]
then
MODE=$1
else
MODE=run
fi

if [ ! -e $LOGDIR ]
then
`mkdir $LOGDIR`
fi

if [ ! -d $LOGDIR ]
then
if [ $MODE = test ]
then
echo “ERROR: $LOGDIR IS NOT DIRECTORY.”
fi
echo “$HOST ERROR: $LOGDIR IS NOT DIRECTORY.” | /bin/mail -s “CPU CHECK ERROR” -c $CC $TO
exit 0
elif [ ! -r $LOGDIR -o ! -w $LOGDIR -o ! -x $LOGDIR ]
then
if [ $MODE = test ]
then
echo “FORBIDDEN: Don’t have permission to $LOGDIR on this server.”
fi
echo “$HOST FORBIDDEN: Don’t have permission to $LOGDIR on this server.” | /bin/mail -s “CPU CHECK FORBIDDEN” -c $CC $TO
exit 0
fi

echo “$DATETIME CPU Load $LOAD%” >> $LOGDIR/cpustat_$DATE.log

if [ $BORDER -lt $LOAD -o $MODE = test ]
then
`/usr/bin/top -b -n 1 > $LOGDIR/top_$DATE-$TIME.log`
fi

if [ $LIMIT -lt $LOAD -o $MODE = test ]
then
echo “$HOST CPU Load $LOAD%” | /bin/mail -s “CPU CHECK Alert” -c $CC $TO
fi

exit 0

CPU使用率を検出してアラート

ここ最近ずっと課題になっていたのがサーバーが過負荷になったときどうやって検知するのかということ、プロセスダウンでもすればわかりやすいがCPU使用率が危険な状態というのはどうしようかといろいろ探してみた。vmstatやtopを使う方法が一般的ですが、topコマンドがRHLとBSDで使い勝手が違いがあったので単純なvmstatを選びました。

どこかに載っていたコマンドですが
/usr/bin/vmstat|/bin/grep -E “^ ?[0-9]”|/usr/bin/awk ‘{print$18}’

このようにgrepでヘッダ部分を省きawkを利用してcpuの部分(BSDだと18番目)を抜き出す。
但し、ウチのBSDだとvmstatの1発目が正確な値を表示してくれないので2回分出力して2行目を取得。
そうするとコマンドはこのようになる。

/usr/bin/vmstat 1 2 | /usr/bin/tail -1 | /usr/bin/awk ‘{print$18}’

grepよりかtail -1の方が簡単だな。
これをアラート設定込みでシェルスクリプトに組み込んだのが下の例です。

#!/bin/sh

TO=webmaster@example.com
CC=user1@example.com

idle=`/usr/bin/vmstat 1 2 | /usr/bin/tail -1 | /usr/bin/awk ‘{print$18}’`
cpu=`expr 100 – $idle`

if [ 90 -lt $cpu ]
then
echo “CPU = $cpu” | mail -s “CPU Alert” -c $CC $TO
fi

exit 0