今までは単純にコマンド入れるだけとか単純な振り分け程度でしたが、一まとめの処理を変数の内容を変えながら実行するものを作ったのでシェルスクリプトでも関数みたいのが作りたいなぁ。
#!/bin/sh
var1=ON
var2=OFF
myfunc () {
echo ARG1=$1, ARG2=$2
}
myfunc $var1 $var2
上記のように書けばよいみたい、さすがにプロトタイプ宣言みたいのはないかなー?関数の定義は実際に使用する前に書かかないと見つからないようです。
UNIXとプログラミングの備忘録
今までは単純にコマンド入れるだけとか単純な振り分け程度でしたが、一まとめの処理を変数の内容を変えながら実行するものを作ったのでシェルスクリプトでも関数みたいのが作りたいなぁ。
#!/bin/sh
var1=ON
var2=OFF
myfunc () {
echo ARG1=$1, ARG2=$2
}
myfunc $var1 $var2
上記のように書けばよいみたい、さすがにプロトタイプ宣言みたいのはないかなー?関数の定義は実際に使用する前に書かかないと見つからないようです。
今日はトンデモな実験。というかここ数年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行目で停止したことがわかります。
以前はプログラムの起動時に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
プロセスは生きているけどフリーズしているとかはまた別の方法で検査します。