なからなLife

geekに憧れと敬意を抱きながら、SE、ITコンサル、商品企画、事業企画、管理会計、総務・情シス、再び受託でDB屋さんと流浪する人のブログです。

topコマンドからログファイルを出力させるために、sedとawkをかじる

topの概要

語り尽くされてますし、manにもすごく丁寧に説明がありますので、見た目だけ。

top - 10:12:59 up 42 min,  3 users,  load average: 0.00, 0.01, 0.05
Tasks: 159 total,   1 running, 158 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.6%us,  0.4%sy,  0.0%ni, 96.8%id,  2.1%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   4048536k total,  1446716k used,  2601820k free,    36404k buffers
Swap:  4194300k total,        0k used,  4194300k free,  1124068k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND            
 2965 root      20   0  158m  27m 9572 S  2.0  0.7   0:09.76 Xorg               
    1 root      20   0 19408 1528 1228 S  0.0  0.0   0:01.51 init               
    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd           
    3 root      20   0     0    0    0 S  0.0  0.0   0:00.01 ksoftirqd/0        
    5 root       0 -20     0    0    0 S  0.0  0.0   0:00.00 kworker/0:0H       
    6 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kworker/u:0        
    7 root       0 -20     0    0    0 S  0.0  0.0   0:00.00 kworker/u:0H      
(以下略)


こんな感じで出力されるので、ただファイルに蓄積していっても、時間推移を見るのも一苦労。

後で集計しやすいように、監視対象カテゴリに絞って出力させる。

色々加工するにはなんだかんだExcelが便利なんだけど、このtopのフォーマットってそのままではとても扱いにくい。
やっぱりExcelに取り込むなら、CSVとかTSVとか固定長とか、そういったものが相性がいい。


なので、それを目指してゴニョゴニョします。


サマリ部

file=には任意の出力先を、Sleepには任意の更新間隔(秒)を。あとはいじる必要は特に無いです。
ワンライナーにしてますが、読みにくい&スクリプトとして保存する際は、素直に見やすい改行形式でどうぞ。


なお、ここでawkがやっていることは、「各行の1つ目の要素が***のものに絞り込む」ってことだけ。この程度だったらgrepでもよいのかな?今回はあえてawk使いたかったのでawkでやってみました。

# top - ロードアベレージ監視
while true;do  file="/tmp/TOP_top.$(date '+%Y%m%d')";  date=$(date '+%Y%m%d %H:%M:%S');  top=$(echo -n $(top -b -n 1 -c -d 0 | awk '$1 == "top"'));  echo "${date} ${top}" >> $file; sleep 15;done;
# Tasks監視
while true;do  file="/tmp/TOP_tasks.$(date '+%Y%m%d')";  date=$(date '+%Y%m%d %H:%M:%S');  top=$(echo -n $(top -b -n 1 -c -d 0 | awk '$1 == "Tasks"'));  echo "${date} ${top}" >> $file; sleep 15;done;
# CPU監視
while true;do  file="/tmp/TOP_cpus.$(date '+%Y%m%d')";  date=$(date '+%Y%m%d %H:%M:%S');  top=$(echo -n $(top -b -n 1 -c -d 0 | awk '$1 == "Cpu(s):"'));  echo "${date} ${top}" >> $file; sleep 15;done;
# メモリ監視
while true;do  file="/tmp/TOP_mem.$(date '+%Y%m%d')";  date=$(date '+%Y%m%d %H:%M:%S');  top=$(echo -n $(top -b -n 1 -c -d 0 | awk '$1 == "Mem:"'));  echo "${date} ${top}" >> $file; sleep 15;done;
# swap監視
while true;do  file="/tmp/TOP_swap.$(date '+%Y%m%d')";  date=$(date '+%Y%m%d %H:%M:%S');  top=$(echo -n $(top -b -n 1 -c -d 0 | awk '$1 == "Swap:"'));  echo "${date} ${top}" >> $file; sleep 15;done;

なお、topのデフォルト起動時は「1」を押すと複数CPUの場合にそれぞれの情報に分かれて表示されるのですが、topのコマンドライン引数としてはサポートされていません。
代わりに設定ファイルで起動時デフォルトを設定できるので、必要に応じてそれを使うことになります。


今回は、「環境やたらにいじれないところで、突発的に短時間の性能監視してくれと言われた時に、さっと実行できるもの」という想定(ていうか現実)の元で使えるものが欲しかったため、あえてその辺りはいじりません。
カスタムする場合は、ここにもmanの日本語訳がおいてあるので、「5. ファイル」の章をしっかり読んで下さい。
Man page of TOP

プロセス部

サンプルは以下となります。
プロセスを特定するもので絞り込みが必要ですので、そのための情報を事前に確認しておく必要があります。
プロセスIDで絞り込む場合、先にtopかpsで監視対象のプロセスIDを確認した後に実行することになります。


# プロセスID - PID=2965の場合
while true;do  file="/tmp/TOP_pid.$(date '+%Y%m%d')";  date=$(date '+%Y%m%d %H:%M:%S');  top=$(echo -n $(top -b -n 1 -c -d 0 -p 2965 | awk '$1 == 2965'));  echo "${date} ${top}" >> $file; sleep 15;done;
# ユーザーID - USER=rootの場合。複数行抽出される可能性が高いので、sedを使っています。
while true;do  file="/tmp/TOP_uid.$(date '+%Y%m%d')";  date=$(date '+%Y%m%d %H:%M:%S');  top -b -n 1 -c -d 0 -u root | sed -n -e /root/p | sed -e "s/^/$date/"  >> $file; sleep 15;done;


絞込の結果が複数になってしまう場合、1行で出力されると非常に扱いにくいので、
1:冒頭の日付を各行に追加
2:改行含めて出力
という要件を加えた結果、こうなりました。


sedの1つ目は、「root」が含まれる行だけを抽出。これもawkgrepと大差ないか。
sedn2つ目は、各行の先頭に日付を追加。先にdateで日付を変数$dateに詰めておき、「^=行頭」に置換させる命令になってます。
echoをかませると、複数行が条件に引っかかった時に1行出力になってしまうようなので、echoはやめてsedの結果をファイルに直接リダイレクトしています。


これで取得したファイルをexcelにでも取り込んであげれば、フィルタもソートもグラフ化もラク。


パワフルなツールsedawk

今までなぜか触れる機会がまったくなかったsedawkですが、ネット検索しながらここまで作れました。


どこでもたいてい使えて非常に強力なツールなので、もっと使い込みたいです。



sed & awkプログラミング 改訂版 (A nutshell handbook)

sed & awkプログラミング 改訂版 (A nutshell handbook)



・・・ウチのカミさん*1が昔sedawkをバリバリ使っていたことを昨晩初めて知った!もう忘れたって。

*1:元DB屋。もう業界離れて10年超