2009年5月30日

何かを監視して screen のステータスラインにメッセージを表示する

プロセスとかハードディスク容量とかとにかく何かを監視して、メッセージを出してほしい場合があります。

screen のステータスラインに出すなら以下のようにします。

例えばハードディスクの容量を監視するなら、以下みたいなスクリプトを書いて、パーミッションを設定しておきます。

#!/bin/sh

capacity=`df $dir|awk 'NR==2{sub("%","",$5);print $5}'`

if [ $capacity -gt 80 ];then
    msg="disk is 80 over!!"

else
    msg=""
fi

echo $msg

で .screenrcに以下みたいに書きます。

backtick 0 2 2 /path/to/shell.sh
hardstatus alwayslastline "%?%{=b rw}%0`%{-} %?"

backtick は 以下みたいな感じです。

backtick id lifespan autorefresh command [args]

一番目のが 「id」 で hardstatus で 「%id`」で参照できます。この例の場合「id」に「0」を採番してるので「%0`」で参照できます。

「lifespan」、「autorefresh」とかで監視間隔を修正します。

hardstatus の「%?」はその間の参照が展開されたら表示するっていわゆる条件分岐です。

なのでこの例だと「%0`」の内容が空文字以外だったら表示されます。

よってこの例だと df の結果でハードディスクが80%以上利用されているとステータスラインに文字が表示されます。

スクリプトを工夫するといろいろできると思います。

何かを監視してターミナルの色を変更する(Mac OS X限定)

@totte が「そういえばCPU負荷率に応じて色が変化する管理コンソールってないのかな。緑→赤で。」と Twitter でつぶやいていた。管理コンソールっていってもいろいろあるので、とりあえず監視できれば良いだろうってことでターミナルでやってみた。

スクリプトは即席なので超いい加減です。

#!/bin/sh

capacity=`df $dir|awk 'NR==2{sub("%","",$5);print $5}'`

if [ $capacity -gt 80 ];then
    background="red"

elif [ $capacity -gt 60 ];then
    background="yellow"
elif [ $capacity -gt 50 ];then

    background="black"
else
    background="blue"
fi

osascript << EOF

tell application "Terminal"
    tell window 1
        set background color to "${background}"
    end tell
end tell
EOF

とりあえずこれで df の結果からハードディスクの利用率を見ることができる。

CPUの負荷だったら、uptime の結果を処理すれば可能です。

であとはこれを cron で回すとか screen で backtick 設定するとかするとターミナルの背景色が変更できる。

これだと AppleScript利用しているけど、もっと普通のやり方があったはずなのだけどなー。

追記 : screen版として何かを監視して screen のステータスラインにメッセージを表示するを追記しました。

追記:よく考えると「管理コンソール」の意味が広いからちがっている気がしてきた。Windowsの「管理コンソール」とか、APサーバの「管理コンソール」とか一杯あるから。何かの「管理コンソール」でとにかく色が変更できれば良いってことならそういう製品がないかなーってことなのかもしれないけど。まあこれはこれで役に立つから良いや。

2009年5月27日

Pythonでパフォーマンス計測

Pythonでパフォーマンスチュニングをしたい場合、Python 2.5 以上なのであれば cProfile を利用してまずどこが遅いのかを計測します。

サンプルソースは以下みたいになります。

import cProfile, pstats, StringIO

prof = cProfile.Profile()
# 関数 main() の速度を計測しています
prof = prof.runctx("main()", globals(), locals())

stream = StringIO.StringIO()
stats = pstats.Stats(prof, stream=stream)

# cumulative で sort します
stats.sort_stats("cumulative")
# 上位 80%まで出力します
stats.print_stats(80)

# たとえばこうやると "docuitls" という名前のつく物だけ上位 10 % を出力します
stats.print_stats("docutils", .1)
# 以下2行はオプション

# stats.print_callees("docutils")
#stats.print_callers("rst", .1)
# 結果をログに出力してみます
logging.info("Profile data:\n%s", stream.getvalue())

logging.info の所は計測したい物がフレームワークを利用したプログラムだったりした場合は、プレームワークのログ機能に変更した方が良いかもしれません。

sort_stats の引数に利用できるキーは以下のような物があります。

出力内容に表示される文字の意味
キー名 意味
'cumulative' 累積時間
'file' ファイル名
'module' モジュール名
'pcalls' プリミティブな呼び出しの回数
'line' 行番号
'name' 関数名
'nfl' 関数名/ファイル名/行番号
'stdname' 標準名
'time' 内部時間

cumulative が大きい物ほど処理に時間がかかっています。

pcalls と time を見て pcalls が異常に多いとか time が高い物を探して修正することになります。