jqで遊んでいたら、なんとなく思いついたので投稿。
用意するもの
CentOS release 6.7
- jq
 - topコマンド
 
top + jq
topのバッチモードとjqで、topの出力をjson形式に変更。
$ top -b -n 1 | head -10 | tee top.txt
top - 01:58:31 up  2:47,  4 users,  load average: 0.00, 0.02, 0.00
Tasks:  99 total,   1 running,  98 sleeping,   0 stopped,   0 zombie
Cpu(s):  2.0%us,  0.9%sy,  0.0%ni, 96.4%id,  0.5%wa,  0.3%hi,  0.0%si,  0.0%st
Mem:    502040k total,   379992k used,   122048k free,    44600k buffers
Swap:  1015804k total,        0k used,  1015804k free,   258188k cached
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    1 root      20   0 19232 1376 1100 S  0.0  0.3   0:00.41 init
    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    3 root      RT   0     0    0    0 S  0.0  0.0   0:00.00 migration/0
# jqでjsonに変換
# メモリの使用率が多いやつ上位10件を取得
$ cat top.txt | jq -rcsR '[ gsub("\n$";"") | splits("\n") | sub(" +$";"") | sub("^ +";"")] | .[0:5] as $titles | .[6:] as $data | {"sys": [$titles | .[] | split(",") | [.[] | sub("^ +";"")]]} as $sys |  [$data[0] | splits(" +") | sub("%";"") | sub("\\+";"")] as $row_keys | $data[1:] | [.[] | [splits(" +")]] | {"task":[.[] | [. as $r | range($row_keys|length) | {"key": $row_keys[.], "value": $r[.]}] | from_entries] | sort_by(.MEM) | reverse | .[:10]} as $task | $sys * $task'
{"sys":[["top - 01:58:31 up  2:47","4 users","load average: 0.00","0.02","0.00"],["Tasks:  99 total","1 running","98 sleeping","0 stopped","0 zombie"],["Cpu(s):  2.0%us","0.9%sy","0.0%ni","96.4%id","0.5%wa","0.3%hi","0.0%si","0.0%st"],["Mem:    502040k total","379992k used","122048k free","44600k buffers"],["Swap:  1015804k total","0k used","1015804k free","258188k cached"]],"task":[{"PID":"1","USER":"root","PR":"20","NI":"0","VIRT":"19232","RES":"1376","SHR":"1100","S":"S","CPU":"0.0","MEM":"0.3","TIME":"0:00.41","COMMAND":"init"},{"PID":"3","USER":"root","PR":"RT","NI":"0","VIRT":"0","RES":"0","SHR":"0","S":"S","CPU":"0.0","MEM":"0.0","TIME":"0:00.00","COMMAND":"migration/0"},{"PID":"2","USER":"root","PR":"20","NI":"0","VIRT":"0","RES":"0","SHR":"0","S":"S","CPU":"0.0","MEM":"0.0","TIME":"0:00.00","COMMAND":"kthreadd"}]}
# 5秒ごとにtop+jq
$ while true ; do top -b -n 1 | jq -rcsR '[ gsub("\n$";"") | splits("\n") | sub(" +$";"") | sub("^ +";"")] | .[0:5] as $titles | .[6:] as $data | {"sys": [$titles | .[] | split(",") | [.[] | sub("^ +";"")]]} as $sys |  [$data[0] | splits(" +") | sub("%";"") | sub("\\+";"")] as $row_keys | $data[1:] | [.[] | [splits(" +")]] | {"task":[.[] | [. as $r | range($row_keys|length) | {"key": $row_keys[.], "value": $r[.]}] | from_entries] | sort_by(.MEM) | reverse | .[:10]} as $task | $sys * $task'; sleep 5; done
topとjqでサーバーのプロセスがjsonで取得できるようになりました。
おまけ
ブラウザ上でリアルタイムに確認したいので、websocketのサーバーとクライアントを作成。
Cargo.toml
[dependencies]
ws = "*"
[[bin]]
name = "ws-server"
path = "src/main.rs"
[[bin]]
name = "ws-client"
path = "src/bin/client.rs"
サーバー
メッセージが来たらブロードキャストするだけ。
src/main.rs
extern crate ws;
fn main() {
    ws::listen("<さーばーのIP>:<ぽーと>", |out| {
        move |msg| { out.broadcast(msg) }
    }).unwrap()
}
クライアント
標準入力から持ってきてサーバーに送信するだけ。
src/bin/client.rs
extern crate ws;
use std::io::Read;
fn main() {
    ws::connect("<さーばーのIP>:<ぽーと>", |out| {
        let mut buf = String::new();
        let _ = std::io::stdin().read_to_string(&mut buf).unwrap();
        out.send(buf).unwrap();
        move |_| { out.close(ws::CloseCode::Normal) }
    }).unwrap();
}
ビルドして実行
$ cargo build --release
# サーバー起動
$ ./target/release/ws-server
# 別のターミナルでクライアントぐるぐる
$ while true; do top -b -n 1 | jq -rcsR '[ gsub("\n$";"") | splits("\n") | sub(" +$";"") | sub("^ +";"")] | .[0:5] as $titles | .[6:] as $data | {"sys": [$titles | .[] | split(",") | [.[] | sub("^ +";"")]]} as $sys |  [$data[0] | splits(" +") | sub("%";"") | sub("\\+";"")] as $row_keys | $data[1:] | [.[] | [splits(" +")]] | {"task":[.[] | [. as $r | range($row_keys|length) | {"key": $row_keys[.], "value": $r[.]}] | from_entries] | sort_by(.MEM) | reverse | .[:10]} as $task | $sys * $task' | ./target/release/ws-client ; sleep 10 ; done
10秒ごとにtopのjsonが送信されてくるので、JSのWebSocket("ws://<サーバーのIP>:<ポート>/")で
ごにょごにょしたらいいと思います。