私のtmuxのステータスラインの紹介

前置き

ステータスラインにcpu使用率とメモリ使用率とネットの通信速度の情報を表示するスクリプトを書いたのでその紹介

注意点(認知しているバグについて)

多重起動を防止するために書いた箇所のせいでスクリプトと同じ名前のファイルをvimなどで開いていると既に起動していると勘違いしてしまいます。気が向いたら直しますが今は不満に思ってないので当分はこのまま…。
それと表示された情報は遅延がありますし特にネットの通信速度はソースコードの都合上それほど正確でもないと思うので注意(パソコンが重いほどずれると思います)

追記2_2012/11/03_13時頃

先ほど書いた、多重起動に関するバグは恐らく直りました。pgrepに-xオプションを足してごにょごにょしました

やり方

その前にこれを使用するとステータスラインは

    [0.61 us, 0.38 sy, 0.00 ni, 0.00 wa, 0.00 id] [0.79 Mem, 0.02 Swap] [11.9 KiB/s down, 1.45 KiB/s up]

こんな感じになる予定。(モダンブラウザは使えないぐらいのパソコンを使用しているので画像は用意してません)
ちなみに数値は好きに色を決めれます

さて、これをやるには私のdotfilesに置いてあるはずのstatus_(cpu|mem|net).shを取ってくる必要があります
今のところはどれも
https://github.com/silenvx/dotfiles/tree/master/misc/default/HOME/.tmux.d
この中に置いてありますが場所を移動したりしてた場合は
https://github.com/silenvx/dotfiles
このリポジトリのどっかにあると思います

さて、それぞれのスクリプトをダウンロードして、好きな場所に配置して実行権限をつけたとします
ここでは私の環境と同じ~/.tmux.dディレクトリ以下においたとします
後はtmuxのステータスラインの左側に表示できるように~/.tmux.confに

    set-option -g status-right '#[fg=white,bold][#[default]#(~/.tmux.d/status_cpu.sh)#[fg=white,bold]] [#[default]#(~/.tmux.d/status_mem.sh)#[fg=white,bold]] [#[default]#(~/.tmux.d/status_net.sh)#[fg=white,bold]]#[default]'

こんな感じに書いておけば使えます
重要なのは#(コマンド名)の箇所ですね。それ以外はただの飾りなので削っても問題はありませんが''で囲う必要はあると思います
これでスクリプトの標準出力をステータスラインに表示できます

もし途切れてしまうのならば

    set-option -g status-right-length 128

このようにステータスラインの左側の文字の長さを大きく指定すればいいです
ちなみにこの箇所の更新の間隔は

    set-option -g status-interval 3

こんな感じで単位は秒で定義できます

これらのスクリプトの設定をいじる

これらのスクリプトソースコードを開けばわかると思うのですが

    # 設定用変数{{{
    #(略)
    # }}}設定用変数

このような箇所が最初の方にあります
vimを使っている場合は折りたたみがされていると思います
その変数はいじることを想定して書いてあります
コメントとして書いてある通りの意味の変数ですので詳しくは割愛しますが

    status_cpu_tmp_file='./tmp/tmp_cpu'

このように書いてある明らかにtmpファイルの変数はカレントディレクトリ以下と指定されていますが
このスクリプトのカレントディレクトリは2行目辺りで定義しているようにそのスクリプトが置いてあるディレクトリです
なのでこれまでの例に習うとこのtmpファイルは~/.tmux.d/tmp/tmp_cpuに作成されます
どういう意味を持つかは後で書きます

このスクリプトの仕様みたいな。中身の話

これらのスクリプトは/proc以下にあるファイルから情報をとってきて数値を生成していますので要はそれに依存しているわけで

    status_cpu.sh
    /proc/[PID]/stat
    /proc/stat

    status_mem.sh
    /proc/[PID]/stat
    /proc/meminfo

    status_net.sh
    /proc/[PID]/stat
    /proc/uptime
    /proc/net/dev

に依存するように書いてあるので無ければ動きません

それぞれのスクリプトは初回起動はデーモン(サーバ)として、2回目以降は初回起動が生成した情報を表示するスクリプト(クライアント)として動きます
初回起動をしたスクリプトは親プロセスが死ぬまで動き続けます(要は普通の使い方をしているならばtmuxを落とせばこれも死ぬ)
親プロセスが生きていればstatus_(cpu|mem|net)_sleep_time秒間隔で情報を取得しにいき、そしてstatus_(cpu|mem|net)_tmp_fileにtmux上に出力したい文字列を書き込み続けます
(本当はHDDに書き込むのではなくメモリ上に書き込みたかったけどやり方がわからないのとHDDに書き込まないのか知りませんがpipeファイルでやろうとしてもうまく書けなかった…)

そしてtmuxから
tmuxの設定、status-interval秒毎に起動される2回目以降のスクリプトはデーモンが生きているのを確認すれば書き込まれているはずのtmpファイルを表示して終了します

ちなみにデーモンはtmuxの初回起動の時には数秒間何も表示されなかったり最初のループの時にはtmpファイルがなかったり、古い情報が入っていたりすると思うので

    start status_cpu.sh

のような文字列を最初にteeを使って標準出力とtmpファイルに書き込むようにしてますが
tmuxのソースコードを見てないのでわかりませんが
恐らくスクリプトが死んでからでないと標準出力の内容が表示されないようで
2回目以降の起動時にデーモンの1回目のループが終了していない時だけ表示されるようで
2回目以降がまだ起動していない場合も表示させるにはどうするか模索中です。表示するだけでも処理を食うので切ったほうがいいかもしれない

と、全体の流れはこのようになっております

次にそれぞれの中身の動きについて(共通部分は端折ります)
status_cpu.sh

/proc/statからcpu全体の情報をまずとってきます(コアごとにとってくる仕組みを書いた方が良かったかもしれませんがマルチコアじゃないので…)
このファイルは起動してからの累計なので差をとるためにstatus_cpu_sleep_time秒後にもう一度とってきて
status_cpu_kind変数を元に数値を前から順にその変数の値を識別名として扱って
それらの数値を足したり引いたりしてそれぞれの識別名の割合を計算してstatus_cpu_viewに書いてある識別名だけを出力してます

status_mem.sh

3つの中で一番適当に書いたものですのでSwapの非表示を考慮してなかったり1行が長かったりしてかなりお粗末になってます。現在は共通部分を除けば4行ぐらいです
/proc/meminfoからMemTotal,MemFree,SwapTotal,SwapFreeで始まる行をとってきて
Free割るTotalをして、Freeの割合を計算させたのち、Free以外の容量、要は使用済みを求めるために1を引いてそれを出力するだけです

status_net.sh

/proc/net/devから情報をとってきますが、通信速度の秒速を知りたいので他の2つと違ってラグが生じても少しぐらいは大丈夫なようにとってくる前後で/proc/uptimeから起動してからの時間もとってきます
このファイルも起動してからの累計なので差をとるためにstatus_net_sleep_time秒後にもう一度同じことをして
status_net_interfaceに書いてあるインターフェイス名で始まる行を抜き出します
もしインターフェイスがなければ抜き出すことができず、何も出力されないのでそれを判定して、何もなければ終了するようにします
もし出力されれば続行して受信と送信に別けて
(受信と送信の順序が逆になったことを考慮して書いてないのはここだけの話)
/proc/net/devから情報をとってくる前後の先ほどとってきた時間の平均で古い送受信と新しい送受信の差を割って秒速を割り出します
桁が変わるとステータスラインが動きまくって目障りだし、かといって桁をそのまま固定する場合はどれぐらい桁をとればいいのかわからないので世の中には単位という便利なものがあるのでそれを使って小数点を含めて数値の箇所はstatus_net_length桁に収まるように計算して出力して終わり

後書き

正直、シェルスクリプトで書いたのはいいものの常駐するものだしC言語で書いたほうがいい気がしてきた
そうすれば簡単にサーバとクライアントが書けそうな気もするけどそんな気力はもうない
ロックファイルを使わずに多重起動のチェックってどうしよう…。起動済みのプロセスからその実行ファイルのフルパスを照らしあわせればいいのかな
わかったらとりあえずひっそりスクリプトを更新しときます

追記1_2012/11/03頃

説明をするのを忘れてましたがデーモンとその他に別ける意味は、情報を出力するのに時間がかかると表示されない時間ができるのでそれを防ぐためにデーモンで常に最新に近い情報をファイルに書き込んで、いつでも出せるようにして2回目以降の起動ですぐにcatをしています