内容的には単純なのだが、ちょっとややこしい部分があって、論理的に考えないと答が出ないようになっている。半分、演習問題のようなテーマだ。
順調に遅延しているのはいいのだが、私自身他に3件も受け持っているので、
「いざ、もう間に合いません」
と言うときになってからスクリプトを書き始めると、ちょっと間に合わなかったりする。なので、ここに模範解答の形で答を書いておこうか、と思う。いざとなったらここを参照すればよいわけだ。
他の人の演習問題にもなったらな、と思うので、問題も全部公開しよう。秘密といえるような部分は一切無い。
課題
request1
/proc/meminfo の内容を定期的に参照して欲しい。/proc/meminfo のデータは1項目一行形式になっているので、これを1行の TSV に直して欲しい。最初の一回だけ、どの項目がどこにあるのかを示すラベルもつけて欲しい。また、最初の要素に、/proc/meminfo の情報をいつ取得したのか、date の情報を "YYYY/MM/DD hh:mm:ss" の形式で保存して欲しい。
request2
/proc/meminfo には Slab という項目がある。ここの値がある閾値を超えたら、定期的に参照するその参照頻度を上げて欲しい。ようするにデータを取る間隔を短くして欲しいのだ。問題は、いったん間隔を短くしたら、二度と長くしないで欲しい、と言うことと、「閾値」は2つ、Yellow と Red があるので、それぞれに応じて間隔を短くして欲しい。また、この閾値はあとで簡単に変更できるように、スクリプトの上のほうの行で名前で宣言して欲しい。もちろん、その際の「間隔」もそれぞれ名前で宣言しておいて欲しい。
request3
Yellow の閾値を超えたら /proc/slabinfo のデータも取ってきて欲しい。こちらは、/proc/slabinfo のファイルの情報の各行の前に "# " (シャープがきて、その次に空白が1つ) をつけた形で、/proc/meminfo のデータを保存しているログファイルと同じ所に保存して欲しい。
課題の詳細
request1
/proc/meminfo を読んでくると次のようなフォーマットで値が出力される。
MemTotal: 1001008 kB
MemFree: 200708 kB
Buffers: 43400 kB
Cached: 395740 kB
SwapCached: 0 kB
Active: 557556 kB
Inactive: 178624 kB
HighTotal: 97216 kB
HighFree: 140 kB
LowTotal: 903792 kB
LowFree: 200568 kB
SwapTotal: 2096472 kB
SwapFree: 2096472 kB
Dirty: 224 kB
Writeback: 0 kB
Mapped: 356492 kB
Slab: 47820 kB
CommitLimit: 2596976 kB
Committed_AS: 689048 kB
PageTables: 6192 kB
VmallocTotal: 114680 kB
VmallocUsed: 4560 kB
VmallocChunk: 107264 kB
HugePages_Total: 0
HugePages_Free: 0
Hugepagesize: 2048 kB
request 1 はようするにこれを
"1001008"<tab>"200708"<tab>"43400"....
のように1行に直して欲しい、という事だ。ただし、<tab> の部分は実際にはタブ文字コード (awk とかだと "\t")で分けて欲しい。また、数字は " で囲ってもらえると助かる。
また、最初の1回だけラベルの部分も欲しい。これはつまり
"MemTotal"<tab>"MemFree"<tab>"Buffers"....
のような行を出して欲しい、と言うこと。
さらに、一番最初にデータを取得した情報が欲しい、とある。これはようするに
date +"%Y/%m/%d %H:%M:%S"
の出力を取り込んで、最初に表示して欲しい、という事だ。当然ラベル行も実際には:
"date"<tab>"MemTotal"<tab>"MemFree"<tab>"Buffers"....
でなくては困る。
request2
/proc/meminfo のSlab:の項目が 358809 未満を Green,
358809 以上 627916 未満を Yellow,
627916 以上を Red
という状態とする。これは32bit Linux Kernel のメモリ領域が 876Mbyte しかなく、それぞれ 40%、70% の所に閾値を用意した、という事だ。実際には Slab が Yellow になることすらめったに無いはずで、Red に突入したら、間違いなく oom-killer が近々発動するだろう。その傾向を見たいのだ。
状態が Green の間は 300秒(5分)間隔で request1 を実施して欲しい。
Yellow になったら 60秒(1分)間隔で request1 と request3 を実施して欲しい。
Red になったら 30秒間隔で request1 と request3 を実施して欲しい。
いったん Yellow になったら、Slab の値が改善しても Green には戻らないで欲しい。同様に Red になったら、Yellow, Green には戻ってはいけない。なので、「今回の Slab の値だけで、次にデータ取得するまでの間隔を決める」のでは困る。
request3
cat /proc/slabinfo を実施するとこんな感じの出力が得られる。
slabinfo - version: 1.1
kmem_cache 60 78 100 2 2 1
blkdev_requests 5120 5120 96 128 128 1
mnt_cache 20 40 96 1 1 1
inode_cache 7005 14792 480 1598 1849 1
dentry_cache 5469 5880 128 183 196 1
filp 726 760 96 19 19 1
buffer_head 67131 71240 96 1776 1781 1
vm_area_struct 1204 1652 64 23 28 1
これの頭に "# " をつけて
# slabinfo - version: 1.1
# kmem_cache 60 78 100 2 2 1
# blkdev_requests 5120 5120 96 128 128 1
# mnt_cache 20 40 96 1 1 1
# inode_cache 7005 14792 480 1598 1849 1
# dentry_cache 5469 5880 128 183 196 1
# filp 726 760 96 19 19 1
# buffer_head 67131 71240 96 1776 1781 1
# vm_area_struct 1204 1652 64 23 28 1
としてほしいわけだ。これは、/proc/meminfo の次の行から出力して欲しい。だから:
"2009/03/01 10:48:58"<tab>"1001008"<tab>"200708"<tab>"43400"....
# slabinfo - version: 1.1
# kmem_cache 60 78 100 2 2 1
# blkdev_requests 5120 5120 96 128 128 1
# mnt_cache 20 40 96 1 1 1
# inode_cache 7005 14792 480 1598 1849 1
# dentry_cache 5469 5880 128 183 196 1
# filp 726 760 96 19 19 1
# buffer_head 67131 71240 96 1776 1781 1
# vm_area_struct 1204 1652 64 23 28 1
:
のような出力が延々続くログファイルが欲しい、という事になる。
背景
oom-killer が発動したシステムがあった。
/var/log/messages に残る oom-killer の行動痕跡によると、slab が異常に大きい。
そこで、slab の状態を記録すると同時に、自分たちが何をやっていたのかを記録する。
slab がでかくなったタイミングで何をやっていたのか知れば、問題点がわかるに違いない。そのための監視用ログシステムが欲しい、と言うわけ。
参考資料
スクリプト言語であれば何を使っても良かったのだが、とりあえず bash と sed と awk ということなので、参考資料は次の通り。
0 件のコメント:
コメントを投稿