こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

load averageの値を監視して自動でコマンドを実行するには?

Redhat Linux で自宅サーバーを運用しています。

コマンド top,uptime,w などで見れる load averageについて、

load average: 0.77, 2.39, 3.38 (1分、5分、15分の平均数値)
このように表示されますが、

load average の1分の平均が 例えば 30 を超えたら、
特定のコマンド(killall hello.cgi)を自動で実行したいと思っています。

さらさらっとサンプルスクリプトを書いて頂けたら
大変嬉しいのですが。。

あと、このスクリプトを実行する方法ですが、
cronだと、たぶん最短間隔でも1分おきにしか
走らせることは出来ないと思います。
極端な話、毎秒、バックグラウンドで常に load average を監視して
1分平均が 30 を超えたら、即座に killall hello.cgi を実行したいです。

どなたかお知恵を拝借下さい。宜しく御願いいたします。

投稿日時 - 2007-12-29 02:54:23

QNo.3635274

すぐに回答ほしいです

質問者が選んだベストアンサー

数え間違いをしてましたm(_ _)m 10番目ですね。心配したのはアップタイムが一日未満の時にずれるのではと思いました。ずれる心配のない、/proc/loadavg が良いですね。
わかりにくかったようなので、ワンステップずつ書いてみます。test コマンドでは実数の比較が出来ないので、小数点以下を削除して整数部分だけ比較することにしています。

#!/bin/bash
A=(`cat /proc/loadavg`) # A[0]=1分平均、A[1]=5分平均、A[2]=15分平均
B=${A[0]} # B=1分平均を実数のまま
C=${B/.*/} # その文字列のピリオドとそれに続く文字を削除・・・切り捨てて整数化する
if test $C -gt 30
then killall xxxxx
echo "$C 件だったのでkillallしました" | /bin/mail -s "killall notice" root
fi

> hello.cgi のみ時々異常回数呼び出され、
cgi側で、ロックファイルなどを使って、「すでにに30多重動いていればエラー画面を返す」ように書き換えた方が良いように思います。
プログラミングのその言語のカテゴリで、
その旨を聞いてみればどうでしょうか?

load average というのは「CPUをもらっている」or「CPU待ち」のプロセス数なので、「ディスクやネットやの入出力待ち等」のプロセスは入りません。

投稿日時 - 2007-12-29 18:40:30

補足

完璧に動作しました。本当にありがとうございました。

hello.cgi について、これを異常回数呼び出しているのは
特定の接続元だと思うのですが、もしkillせずに30以上
動いている場合はエラーを返すようにcgiを書き換えると、
こやつのみに、hello.cgi が占有されてしまう気がします。。
こやつが誰なのか一生懸命探っているんですが分かりません。

topで監視していると hello.cgi がズラッと並ぶんですが、
これらの接続元IPを知るにはいったいどうしたらよいでしょうか。
別の質問になってしまいますが、もしアドバイスいただけましたら
うれしいです。

ちなみに 
$lsof -i:80 |grep -v LISTEN  とか
$netstat -np |grep httpd  とかを
watchコマンドで 1秒間隔で監視していますが、
hello.cgi へアクセスしているIPというのは直接表示されず
補足出来ません。(apache のプロセスを表示しているはずなんですが・・)

また、top で拾ったhello.cgi のPID を、即座に
netstat -p | grep PID を使って接続元を特定しようとしますが
PID は一瞬で変わり消えてしまうため補足出来ません。

アクセスログも当然監視していますが、同じIPがズラズラ表示されることもなく、
どういった種類のアクセスがこういった異常を引き起こすのか悩んでいます。

投稿日時 - 2007-12-30 01:51:47

ANo.2

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.3

cgiプロセスはIP通信をしません。Apacheがクライアントと通信して、データを受け取ったら、cgiプロセスを起動して、環境変数とパイプ経由でデータをcgiプロセスの標準入力にわたし、cgiプロセスは標準出力をパイプ経由でapacheにわたし、apacheはそれを処理結果としてクライアントに送ります。

従って、試みられた方法は無意味です。

cgiの中では環境変数 REMOTE_ADDR にクライアントのIPアドレスが入りますから、cgiの開始時と終了時に、
時刻・開始/終了・プロセスID・REMOTE_ADDR
をsyslogにでも記録すると、何らかの手がかりがあるかもしれません。

具体的な方法は、その言語のカテゴリで聞いてください。

一応、ありがちな原因として、cgiプログラムがループして居座っているという可能性は無いのですか?

投稿日時 - 2007-12-30 12:53:30

補足

なるほど、どおりでnetstatでは見つからなかったわけですね。
大変勉強になりました。

>cgiの中では環境変数 REMOTE_ADDR にクライアントのIPアドレスが入りますから、cgiの開始時と終了時に、
時刻・開始/終了・プロセスID・REMOTE_ADDR
をsyslogにでも記録すると、何らかの手がかりがあるかもしれません
具体的な方法は、その言語のカテゴリで聞いてください。

そういう方法もあるんですね。
cgiがループしている可能性は、よくわかりません。。
1日中、普通に動いていながら、だいたい毎日同じ時間帯に大量起動が発生するため、プログラム自身に問題があるわけではなく、誰かの悪意あるアクセスなのかなと思いました。

今回は色々勉強になり助かりました。ありがとうございました。

投稿日時 - 2007-12-31 00:12:00

ANo.1

#!/bin/bash # bashを前提
A=(`uptime`) # 配列Aにuptimeの結果をバラして格納
B=${A[10]/.*/} # 11番目(添え字は0からなので10)が1分平均。そのピリオド以降を削除してBに
if test $B -gt 30
then killall xxxxx
fi

こんな感じですかね。ただしuptimeの11番目が常に1分平均かは未確認。前半の表示結果次第で変わるのかも。

ただ、cgiの数を制限したいのなら、apacheのconfファイルでプロセスやスレッドの最大値を制限した方が良いのでは?

投稿日時 - 2007-12-29 10:23:38

補足

ご回答ありがとうございます。1分平均が何番目か、について、

$ uptime では常に、

14:23:08 up 34 days, 4:06, 1 user, load average: 0.67, 0.63, 0.58

というフォーマットで表示されます。よって1分平均の値は10番目、

$ uptime | gawk '{ print $10 }' と打つと、常に以下のように
コンマ付きで1分平均の値が表示されました。

0.67,

つまり添え字が0からということだと、正しくは9番目以降を削除して。。となるのでしょうか。
また、コンマを消すために、
(B=${A[9]/,*/}) でしょうか?



1分平均の値は他にも /proc/loadavg の1番目に表示できました。

$ cat /proc/loadavg と打つと、

0.79 0.71 0.62 3/161 25388

このコマンドを使う場合は・・
添え字が0からなので、1番目のスペース以降を削除して。。

#!/bin/bash
A=(`cat /proc/loadavg`)
B=${A[0]/``*/}
if test $B -gt 30
then killall xxxxx
fi

でしょうか?


あと、killall xxxxx したら、root宛に通知メールを送りたいのですが
どのように記述すればよいでしょうか。
(root 宛のメールは、外部のメールアドレスに転送されるようにしてあります)



>ただ、cgiの数を制限したいのなら、apacheのconfファイルでプロセスやスレッドの
>最大値を制限した方が良いのでは?

はい、確かに killall は根本的な解決ではありません。
hello.cgi のみ時々異常回数呼び出され、
その接続元もどうしても特定できず、
サーバーが不安定になります。とりあえずkill したいと考えています。

投稿日時 - 2007-12-29 14:00:34

あなたにオススメの質問