Core吐かせてみよう

今日はトンデモな実験。というかここ数年Core吐かせてないのでデバッグ用にわざと吐かせてみた。

#include
int main(){
int i=0;int j=1;int k=0;
printf(“i=%d,j=%dn”,i,j);
k=j/i;
printf(“k=%dn”,k);
return 0;
}

コンパイル
> gcc -o fault fault.c

実行
> ./fault
i=0,j=1
Floating exception (core dumped)

まぁ酷いプログラムです。
実行すればたちまち0除算が原因でcoreを吐きます。
今までWindowsも含めてコアダンプを利用した解析なぞやったこと無かったので、バイナリエディタで開く…。全く読めない。そこで調べていたらgdbコマンドを使えば直ぐにわかるという。これがあれば解析のためにガリガリファイルにログを書き出さなくていいかもです。

まずは試しに実行。(実行ファイル名はfaultでコアダンプはfault.coreです)

> gdb fault fault.core
#0 0x0804854e in main ()

main関数でダウンしたことがわかります。

今度はデバッグモードでコンパイル(特に再実行してコアを更新する必要はなさそうです)
> gcc -g -o fault fault.c
> gdb fault fault.core
#0 0x0804854e in main () at fault.c:8
8 k=j/i;

なるほど、fault.cの8行目で停止したことがわかります。

pgrepを使ってプロセス監視

以前はプログラムの起動時にPIDを入れた一時ファイルを作成する方法をとっていましたが、その方法が通用するのは正常起動・終了が前提で起動監視としては機能不足です。
時々チャットサーバーが落ちていることがあるため(まったく原因が不明)起動監視&アラート送信を行います。その時にプロセス監視を行うためにpgrepを使用しますが、下記の項目に気をつけないとイタイ目にあいます。

Q1. デフォルトではプロセス名が部分一致なので予期しないプロセスがマッチする。
A1. xオプションをつけて完全一致にさせる

Q2. 同じプロセスが存在する。
A2. uまたはUオプションでユーザーを指定するかfオプションでディレクトリも確認する。それでも複数ヒットする場合は…。(a.outとか安易にマッチしそうな名前にしないこと?)

Q3. プロセス名が長いとマッチしない
A3. OSによるがfオプション無しの場合一定文字列長でプロセス名が切り捨てられる。fオプションをつけるか、lオプションでマッチしたプロセス名を確認する。

以上の注意よりコマンドでは下記のように検査する。

# pgrep -f -x -U username ./socket_server
10042

プロセスが生きていればこのようにPIDが出てきて(複数だと複数行に)生きてなければ空を返します。
これを利用してcrontabで監視する場合はこちら

#!/bin/sh
TARGET=socket_server
cd $TARGETDIR
ret=`pgrep -f -x -U $USER ./$TARGET`
if [ -z $ret ]; then
echo ‘SERVER IS DEAD’ | mail -s ‘NOTIFY’ info@test.net
./serverctrl.sh start
fi

crontabを利用せず、バックグランドで見張る場合はsleepで永久ループ。ただしこれ自身が落ちたら意味ない。

#!/bin/sh
INTERVAL=15
TARGET=socket_server
cd $TARGETDIR
while true; do
ret=`pgrep -f -x -U $USER ./$TARGET`
if [ -z $ret ]; then
echo ‘SERVER IS DEAD’ | mail -s ‘NOTIFY’ info@test.net
./serverctrl.sh start
fi
sleep $INTERVAL
done

プロセスは生きているけどフリーズしているとかはまた別の方法で検査します。

mailコマンドで自動送信

万が一、プロセスが停止したときも考えてシェルからメールを送ってみたい。
今のところ確認した方法はmailコマンドを利用したもの。

本文もコマンドに書く場合
echo ‘本文’ | mail -s ‘タイトル’ <メールアドレス>

テキストファイルを本文にする場合
cat <ファイル名> | mail -s ‘タイトル’ <メールアドレス>

ファイルを添付(この方法は自宅FreeBSDにunencodeコマンドが無かったので未実証)
unencode <ファイルパス/ファイル名> <添付ファイル名> | mail -s ‘タイトル’ <メールアドレス>

これでサーバーからのアラートメールを受け取れます。