やっぱり Sun がスキ! : Weblog やっぱり Sun がスキ!

やっぱり Sun がスキ!

http://blogs.sun.com/yappri/date/20090624 2009年 6月 24日 水曜日

統計情報を一挙に取得するスクリプト

はじめに

今回はシステムの性能情報をまとめて取得するスクリプトをご紹介したいと思います。私が普段ベンチマークテストを行う時に使用しているスクリプトです。

システムの性能を解析する際は、解析対象のシステムの負荷が高い時に現場で解析を行う事が鉄則です。稼働中のシステムに接続して、コマンドの結果を見ながら問題範囲を狭めて行くと、効率の良い解析が出来るからです。しかし現実的には、常にシステムの負荷が高い時に解析を行える訳ではありません。何らかの事情で現場に行く事が出来ず、他の人に統計情報の取得を依頼して、後からログを解析する様な事は良くあります。また、誰かに性能解析を依頼する場合も、あらかじめ必要なログを取得しておき現場から離れた場所で解析して貰う事があります。

現場で解析が出来無い場合は、入手する必要のある情報を解析の前に考えておかなければなりません。まだ状況が不明な状態でどのログを取るべきかを決定するのは困難ですので、通常は網羅的に統計情報を取得しておく事になるでしょう。広範囲に情報を取得しておけば、解析する段になって情報が不足する事を防げるからです。従来であれば、そのような時に使用するツールは sar(1) であったり、rpc.rstatd(1M) を使用した統合監視ユーティリティがありました。ここでの問題は sar(1) や rpc.rstatd(1M) は必ずしも必要なデータを取得出来ない事、そして不足している情報があってもカスタマイズ出来ない事です。

この様な時に自分で修正可能なスクリプトを持っていると便利です。「ちょっと現場に立ち会えないんだけど、このスクリプトを実行してログを送ってもらえる?」と言っておき、時間がある時にゆっくり解析を進める事も可能です。急な出張が入ってしまったり、ちょっと体調を崩して出社出来なかったり、同時に複数のサイトを調査する必要が出ても、これがあれば多少は安心です。厳しいセキュリティによりログを持ち出せない場合でも常にマシンに張り付いている必要は無くなります。

前置きが長くなりましたが、後で解析出来る様に統計情報をまとめて取得しておく為のスクリプトのご紹介です。

使い方

基本的な使い方

この記事の一番下にあるスクリプトを stat.sh という名前で保存し、実行権限を付け、実行します。

 # mkdir /var/tmp/stat
 # cd /var/tmp/stat
 # vi stat.sh
 # chmod +x ./stat.sh
 # ./stat.sh
 Ctrl-C to stop this.

Ctrl-C を押すと実行が終了します。何も押さなければ延々と統計情報を取得し続けます。

結果の見方

スクリプトを実行したディレクトリに log ディレクトリが作成され、そこに統計情報のログが保存されています。

 # ls log
 0619-172209.about.txt        0619-172209.netstat-tcp.log
 0619-172209.cfgadm-alv.log   0619-172209.netstat.log
 0619-172209.defaultrouter    0619-172209.nodename
 0619-172209.dladm-bge0.log   0619-172209.nsswitch.conf
 0619-172209.dladm.log        0619-172209.prstat.log
 0619-172209.format.log       0619-172209.prtdiag-v.log
 0619-172209.hosts            0619-172209.ps-ef.log
 0619-172209.ifconfig-a.log   0619-172209.psrinfo.log
 0619-172209.iostat.log       0619-172209.psrset.log
 0619-172209.kmastat.log      0619-172209.release
 0619-172209.messages         0619-172209.system
 0619-172209.mount.log        0619-172209.uname-a.log
 0619-172209.mpstat.log       0619-172209.vfstab
 0619-172209.ndd-ip.log       0619-172209.vmstat-p.log
 0619-172209.ndd-tcp.log      0619-172209.vmstat.log
 0619-172209.netstat-nr.log

ファイル名の先頭の 0619-172209 は日付と時間です。6/19 の 17:22:09 にスクリプトを実行しました。

各ファイルには最長 1 時間分のログが保存されます。スクリプトの実行が 1 時間を越えると、自動的に新しいファイルが作成され、ログは新しいファイルに保存されます。

取得される情報はファイル名の通りです。XXXX-XXXXXX.vmstat-p.log には "vmstat -p 1" を実行した結果が保存され、XXXX-XXXXXX.cfgadm-alv.log には "cfgadm -alv" を実行した結果が保存されています。vmstat, mpstat, iostat 等、基本的な統計情報から解析を始めて下さい。

結果を保存する

log ディレクトリを gtar と bzip2 で固めるだけです。この状態で性能解析を担当する人に渡してあげれば便利です。

 # gtar jcf ./log.tar.bz2 ./log

その他

stat.sh の引数にコメントを指定する事が出来ます

 # ./stat.sh "MySQL 5.4 Benchmark"
 Ctrl-C to stop this.
 ^C
 # cat ./log/*.about.txt
 MySQL 5.4 Benchmark

取得したい統計情報があれば、必要に応じてスクリプトを改変して下さい。

おわりに

Solaris の統計情報を網羅的に取得するスクリプトをご紹介しました。Solaris を管理する上で、こういうダーティーなスクリプトが役に立つ局面もあるのではないかと思います。是非、色々と改造して使って下さい。

もし GUI で統計情報を見たい場合は Dim STATJKstat もご覧下さい。

スクリプト

 #!/bin/sh
 
 IVAL=1
 DURATION=3600
 DIR=./log
 
 SH_PID=$$
 PID=${SH_PID}
 COMMENT=$@
 
 if [ ! -d ${DIR} ]
 then mkdir ${DIR}
 fi
 
 LANG=C; export LANG
 LC_ALL=C; export LC_ALL
 
 echo "Ctrl-C to stop this."
 
 while :
 do DATE=`date '+%m%d-%H%M%S'`
 
 echo ${COMMENT} > ${DIR}/${DATE}.about.txt
 
 # system configurations
 cp /etc/nodename ${DIR}/${DATE}.nodename &
 uname -a > ${DIR}/${DATE}.uname-a.log &
 cp /etc/release ${DIR}/${DATE}.release &
 cp /etc/system ${DIR}/${DATE}.system &
 cp /var/adm/messages ${DIR}/${DATE}.messages &
 prtdiag -v > ${DIR}/${DATE}.prtdiag-v.log &
 cfgadm -alv > ${DIR}/${DATE}.cfgadm-alv.log &
 psrinfo > ${DIR}/${DATE}.psrinfo.log
 psrset > ${DIR}/${DATE}.psrset.log &
 
 # network configurations
 ifconfig -a > ${DIR}/${DATE}.ifconfig-a.log &
 dladm show-link > ${DIR}/${DATE}.dladm.log
 dladm show-dev > ${DIR}/${DATE}.dladm.log &
 cp /etc/defaultrouter ${DIR}/${DATE}.defaultrouter &
 cp /etc/nsswitch.conf ${DIR}/${DATE}.nsswitch.conf &
 cp /etc/hosts ${DIR}/${DATE}.hosts &
 netstat -nr > ${DIR}/${DATE}.netstat-nr.log &
 netstat -a > ${DIR}/${DATE}.netstat.log &
 
 # disk configuration
 echo | format > ${DIR}/${DATE}.format.log &
 cp /etc/vfstab ${DIR}/${DATE}.vfstab &
 mount > ${DIR}/${DATE}.mount.log &
 #luxadm probe > ${DIR}/${DATE}.luxadm-probe.log &
 #luxadm -e port > ${DIR}/${DATE}.luxadm-port.log &
 
 # kernel memory usage
 echo ::kmastat | mdb -k > ${DIR}/${DATE}.kmastat.log &
 
 # ndd
 echo "tcp_time_wait_interval" >> ${DIR}/${DATE}.ndd-tcp.log
 ndd -get /dev/tcp tcp_time_wait_interval >> ${DIR}/${DATE}.ndd-tcp.log
 echo "tcp_conn_req_max_q" >> ${DIR}/${DATE}.ndd-tcp.log
 ndd -get /dev/tcp tcp_conn_req_max_q >> ${DIR}/${DATE}.ndd-tcp.log
 echo "tcp_conn_req_max_q0" >> ${DIR}/${DATE}.ndd-tcp.log
 ndd -get /dev/tcp tcp_conn_req_max_q0 >> ${DIR}/${DATE}.ndd-tcp.log
 echo "tcp_keepalive_interval" >> ${DIR}/${DATE}.ndd-tcp.log
 ndd -get /dev/tcp tcp_keepalive_interval >> ${DIR}/${DATE}.ndd-tcp.log
 echo "tcp_naglim_def" >> ${DIR}/${DATE}.ndd-tcp.log
 ndd -get /dev/tcp tcp_naglim_def >> ${DIR}/${DATE}.ndd-tcp.log
 echo "tcp_smallest_anon_port" >> ${DIR}/${DATE}.ndd-tcp.log
 ndd -get /dev/tcp tcp_smallest_anon_port >> ${DIR}/${DATE}.ndd-tcp.log
 echo "tcp_max_buf" >> ${DIR}/${DATE}.ndd-tcp.log
 ndd -get /dev/tcp tcp_max_buf >> ${DIR}/${DATE}.ndd-tcp.log
 echo "tcp_conn_hash" >> ${DIR}/${DATE}.ndd-tcp.log
 ndd -get /dev/tcp tcp_conn_hash >> ${DIR}/${DATE}.ndd-tcp.log
 echo "tcp_bind_hash" >> ${DIR}/${DATE}.ndd-tcp.log
 ndd -get /dev/tcp tcp_bind_hash >> ${DIR}/${DATE}.ndd-tcp.log
 echo "tcp_listen_hash" >> ${DIR}/${DATE}.ndd-tcp.log
 ndd -get /dev/tcp tcp_listen_hash >> ${DIR}/${DATE}.ndd-tcp.log
 echo "ip_conn_status" >> ${DIR}/${DATE}.ndd-ip.log
 ndd -get /dev/ip ip_conn_status >> ${DIR}/${DATE}.ndd-ip.log
 echo "ip_squeue_fanout" >> ${DIR}/${DATE}.ndd-ip.log
 ndd -get /dev/ip ip_squeue_fanout >> ${DIR}/${DATE}.ndd-ip.log
 echo "ip_soft_rings_cnt" >> ${DIR}/${DATE}.ndd-ip.log
 ndd -get /dev/ip ip_soft_rings_cnt >> ${DIR}/${DATE}.ndd-ip.log &
 
 # process list
 ps -ef > ${DIR}/${DATE}.ps-ef.log
 
 # trapstat
 # trapstat -t 1 3 > ${DIR}/${DATE}.trapstat.log &
 
 # prstat
 prstat -n 50 1 60 > ${DIR}/${DATE}.prstat.log &
 
 # vmstat
 vmstat ${IVAL} ${DURATION} > ${DIR}/${DATE}.vmstat.log &
 PID="$! ${PID}"
 
 # vmstat -p
 vmstat -p ${IVAL} ${DURATION} > ${DIR}/${DATE}.vmstat-p.log &
 PID="$! ${PID}"
 
 # iostat
 iostat -xnCMmp ${IVAL} ${DURATION} > ${DIR}/${DATE}.iostat.log &
 PID="$! ${PID}"
 
 # mpstat
 mpstat ${IVAL} ${DURATION} > ${DIR}/${DATE}.mpstat.log &
 PID="$! ${PID}"
 
 # netstat
 netstat -sP tcp ${IVAL} ${DURATION} > ${DIR}/${DATE}.netstat-tcp.log &
 PID="$! ${PID}"
 
 # network performance counter
 NIC=`dladm show-dev -p | grep 'link=up' | awk '{printf "%s ", $1}'`
 
 for i in ${NIC}
 do dladm show-dev -s -i 1 ${i} > ${DIR}/${DATE}.dladm-${i}.log &
 DL_PID="$! ${DL_PID}"
 done
 
 trap "kill -9 ${DL_PID} ${PID}
 echo 'script done' " 2
 
 sleep ${DURATION}
 kill -9 ${DL_PID}
 
 PID=${SH_PID}
 DL_PID=""
 
 done