rcmdnk's blog

20150519_cpuspark

GitHubで面白そうなシェルスクリプトを探してる時に見つけた Spark by holman について。

数値を棒グラフ上に表示してくれるスクリプトです。

Spark

Spark は数値群を引数に与えるか標準入力で与えてあげると その数値群を棒グラフに変換してくれるシェルスクリプトです。

インストールはGitHubのレポジトリ から直接sparkというスクリプトファイルを取ってきてPATHの通った所に入れるか、 MacであればHomebrewで

$ brew install spark

でsparkコマンドが使えるようになります。

使い方は非常にシンプルで

$ spark 0 20 40 60 80 100
▁▂▃▅▆█

こんな感じで数値を与えるとそれを棒グラフにしてくれます。

インプットに使える数字は少数も使えますが、 実際に使われる際には小数点以下を切り捨てて扱います。 また、負の数値も使うことが出来ます。

グラフを作る際には、最小値と最大値がそれぞれ 一番小さな高さと大きな高さになるように計算され、 高さは最大、最小の点を含めて8つあって等分感覚で振り分けられます。 (正確には最大の値だけが一番大きな線に、後の数値は 最小と最大の数値を7分割してそれぞれの大きさに振り分けられます。)

$ spark 0 20 40 60 80 199 200
▁▁▂▃▃▇█

な感じ。今度は200が最大ですが、すぐ隣りの199は1つ小さい大きさ。 一方、最初の0から20離れていても20は一番小さな大きさ(200/7~28なので)。

仕組みも結構シンプルで コメントやヘルプ等を除いたら実質30行程度で作られています。

spark/spark at master · holman/spark

コードをちょっと見てみると、

local ticks=(▁ ▂ ▃ ▄ ▅ ▆ ▇ █)

という行があって、単にこの8つの文字を使って、 後は数値を適時各大きさに割り振って出力しているだけです。

この文字達はブロック要素と呼ばれる文字達で Unicodeの0x2581から0x2589に当たる文字達です。

Unicode 文字 名前
0x2581 ▁ Lower One Eighth Block
0x2582 ▂ Lower One Quarter Block
0x2583 ▃ Lower Three Eighths Block
0x2584 ▄ Lower Half Block
0x2585 ▅ Lower Five Eighths Block
0x2586 ▆ Lower Three Quarters Block
0x2587 ▇ Lower Seven Eighths Block
0x2588 █ Full Block

HTML Unicode UTF-8

後、途中で分割する際に(max-min)<<8や(n-min)<<8みたいな事をして、 整数割り算した時に1以下になって丸め込まれるのを防ぐ様な事をしてますが、 これは単に表示する所を

-local f=$(( (($max-$min)<<8)/(${#ticks[@]}-1) ))
+local f=$((max-min))
 (( f < 1 )) && f=1

 for n in $numbers
 do
-  echo -n ${ticks[$(( ((($n-$min)<<8)/$f) ))]}
+  echo -n ${ticks[$(( (n-min)*(${#ticks[@]}-1)/f ))]}
 done

な感じでシンプルに行けば良いと思うんですが、何か勘違いしてるのかな。。。? (もしくは昔小数点をなんとか扱おうとしてた時の名残とか?)

使用例

Wicked Cool Usage · holman/spark Wiki に行くと色々載ってますが、 自分でもちょっと作ってみました。

cpu_spark.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#!/usr/bin/env bash

# Parameters
NBINS=20
INTERVAL=1
PROCESSES=("firefox")

# Set process
if [ $# -gt 0 ];then
  PROCESSES=("$@")
fi

# Prepare initial bins
for i in $(seq 0 $((${#PROCESSES[@]}-1)));do
  eval bins_${i}=\(\)
  for j in $(seq 1 $NBINS);do
    eval bins_${i}=\(\${bins_${i}[@]} 0\)
  done
done
bins=()

# Finalization
finalize () {
  # Show cursor
  tput cnorm >/dev/tty 2>/dev/null || tput vs >/dev/tty 2>/dev/null

  # Show input
  stty echo

  # Go to the clean line
  echo
}

# Set trap
trap "finalize;echo;exit" HUP INT QUIT ABRT SEGV TERM

# Hide cursor/input
tput civis >/dev/tty 2>/dev/null || tput vi >/dev/tty 2>/dev/null
stty -echo

# Main loop
while [ 1 ];do
  for i in $(seq 0 $((${#PROCESSES[@]}-1)));do
    cpu=$(ps ax -o %cpu -o comm|grep "${PROCESSES[$i]}\$"|head -1|awk '{print $1}')
    eval bins_${i}=\(\${bins_${i}[@]:1} \$cpu\)
    printf "%${NBINS}s %4s%% ${PROCESSES[$i]}\n" "$(spark $(eval echo \${bins_${i}[@]}) 100)$(tput cub 1)" $cpu
    tput cub $((NBINS+6))
  done
  tput cuu ${#PROCESSES[@]}
  sleep $INTERVAL
done

こんな感じのスクリプト。

psで見れるCPU情報を使って、特定のプロセスのCPU使用率をグラフ化するものです。

cpuspark

こんな感じで引数にプロセス名を入れてあげるとその使用率をグラフ化してくれます。 複数のプロセスでもOK。 (ただ、同じプロセス名の物が複数あったりすると一番上に来るものを取ってくるだけになります。 ソートしたりしてもいいんですが、BSDとGNUのpsでその辺のオプションが違ったりして面倒なので 取り敢えずバージョン。)

なんだかんだでspark自身よりも複雑になってしまった感はありますが、 こんな感じのリアルタイムなグラフをターミナル上に書くことも可能になります。

spark自身は結構単純なスクリプトですが、 今回一番使えるな、と思ったのは ブロック要素の文字列たちで、 ここで使った以外にも横方向に縮めた線や 一マスを4分割にしてそのうちの一部を表示する文字があって、 これらがあるとAscii artとかも色々出来る事増えるな、と。

Sponsored Links
Sponsored Links

« Firefoxに統合されたというPocketはユーザー側にはメリットが無い? Evernoteの新しい体系でもメールで50通までメール作成が無料でも出来る »

}