Network Users' Group ``wheel'' / Dai ISHIJIMA's Page /
RTA55i / SNMPを使わずにMRTG
| はじめに | シェルスクリプトで | syslogで | httpで |
wgetでMRTGその2netstatで
拒否パケットをifconfigでapacheのログを

最終更新日: 2009-04-18


あえてSNMPを使わずにMRTG


●はじめに

MRTGは、「Multi Router Traffic Grapher」という名称が示すとおり、 (SNMPを喋る)ルータなどのトラフィック(トラヒック)を可視化するソフトです。

でも、可視化したい監視対象がSNMPを喋らなかったら…、
あるいは、SNMPが防火壁やNAT箱でブロックされていたら…、
それとも、ズボラにSNMPをインストールしたくない…

大丈夫。MRTGは大変よくできたソフトです。 SNMPを使わなくても(使えなくても)、 いろんな時系列情報を可視化できます。


●シェルスクリプトを使う

MRTGのドキュメントの設定リファレンス ($src/doc/reference.1) で きちんと説明されていますが、可視化したいデータを集める手段として、 外部プログラムを呼び出す方法があります。 詳しいことは、そう、ここで長々と書くまでもないでしょう。
	Target[ターゲット名]: `外部プログラム`
のように、バッククォートで外部プログラムを指定します。

え、ちゃんと説明が必要? わたしのヘタな説明より 公式日本語サイトwww.mrtg.jp/doc/) の MRTG設定リファレンスreference.html) を読んだほうがいいでしょう。

外部プログラムは、設定リファレンスによると、 4行の情報を返すように作っておけば大丈夫です。 各行にどんな情報を出力するかですが、

  1. 入力バイトカウント(目的よっては別にバイトカウントでなくてもいい)
  2. 出力バイトカウント(目的よっては別にバイトカウントでなくてもいい)
  3. 稼働時間(人間可読形式で。要するに一行テキスト)
  4. 監視対象の名前

具体例は、netstatでMRTGをどうぞ。

監視対象はルータやトラフィックなどに限定されるわけではありません。 たとえば、サーバの温度なんかを可視化したい場合もあるでしょう。 マザーボードのハードウェア情報を教えてくれるhealthdというツールがありますが、 これを使って、CPU温度とマザーボード温度を1/10度単位で監視したいなら、

	#! /bin/sh

	export LANG=C
	temp=/tmp/x.$$
	trap 'rm -f $temp*; exit 1' 1 2 15		# clean up files

	/usr/local/sbin/healthd -dc 1 | grep '^Temp'  > $temp.1
	ibytes=`cat $temp.1 | awk '{print $2*10}'`
	obytes=`cat $temp.1 | awk '{print $3*10}'`

	echo $ibytes
	echo $obytes
	echo 0
	echo "healthd monitoring"

	rm -f $temp*
	exit 0

	# EOF
みたいなシェルスクリプトを用意して、
	#
	# mrtg.cfg -- healthd
	#

	WorkDir: 	/path/to/work
	HtmlDir:	/path/to/html
	ImageDir:	/path/to/image
	LogDir:		/path/to/log
	IconDir:	/path/to/icon

	# absolute - 得られた値を間隔(300秒)で割ってグラフ化
	# gauge    - 得られた値をそのままグラフ化
	# 指定なし - 得られた値と直前の値の差を間隔(300秒)で割ってグラフ化
	Options[_]: gauge,growright,nopercent,withzeroes

	Target[healthd]: `/bin/sh /usr/local/libexec/healthd.sh`
	MaxBytes[healthd]: 2000
	Title[healthd]: healthd monitoring (temperature)
	YLegend[healthd]: Celsius x10
	ShortLegend[healthd]: deci C
	LegendI[healthd]: CPU Temp
	LegendO[healthd]: System Temp
	PageTop[healthd]: <H1>Temperature (deci Celsius)<H1>
	Legend1[healthd]: CPU Temperature (deci Celsius, ie. 200 means 20 degrees celsius)
	Legend2[healthd]: System Temperature (deci Celsius)

	# EOF
という設定ファイルを用意すればいいでしょう。


●syslogを使う

監視・可視化したい情報がMRTGを動かしているローカルマシンで動いていれば、 前節のように適当なシェルスクリプトを用意してやればどうにでもできます。 しかし、リモートマシンの情報を監視したいときは? やはりその監視対象がSNMPを喋るようにするのがふつ〜です。

とはいえ、諸般の事情でSNMPを喋らせることができない場合もまれにはあるでしょう。 そういうときは、そこに何か追加しないで、リモートマシンの情報を MRTGを動かしているマシンに伝達する方法を考えましょう。 UN*X系のマシンなら、いろんな方法があります。

たとえば、syslog。

UN*X系マシンには、logger(1)コマンドが用意されています。 可視化したい情報をloggerコマンドでMRTGが動いているマシンに送り、 MRTGが動いているマシンで、 ログから前節で書いたような4行形式のデータに変換して MRTGでグラフ化してやればよいのです。


●httpを使う

監視対象が防火壁やNAT箱の内側にいるときは、 SNMPはおろか、syslogもブロックされて通らないこともあるでしょう。 では、どういうプロトコルなら通りそうでしょうか。 可能性として高いのはhttp (80/tcp) ではないでしょうか。

例として、メールのトラフィックを監視する場合のスクリプトを以下に。

	#! /bin/sh
	#
	#  smtp.sh -- HTTPリクエストでMRTG用データを送信する
	#
	#	0.0: Mar. 27, 2009 by Dai ISHIJIMA
	#

	export LANG=C
	export PATH=/usr/bin:/bin:/usr/local/bin:/usr/sbin:/sbin

	temp=/tmp/x.$$
	trap 'rm -f $temp*; exit 1' 1 2 15		# clean up files

	request=http://mrtg.your.domain/path/to/monitor/
	epoch=`date '+%s'`
	host=`hostname -s`
	target='smtp'

	ibytes=`grep 'smtpd.*: connect from' /var/log/maillog | wc -l | awk '{print 0 + $1 * 1000}'`
	obytes=`grep 'relay=.*status=sent' /var/log/maillog | wc -l | awk '{print 0 + $1 * 1000}'`

	wget -O - -q "${request}?host=${host}&epoch=${epoch}&target=${target}&ibytes=${ibytes}&obytes=${obytes}"

	rm -f $temp*
	exit 0

	# EOF
このスクリプトは、wgetコマンドを使って、MRTGが動いているマシンに、 /var/log/maillogの情報(PostfixでSMTPクライアントが接続してきた数と メール送信に成功(status=sent)した数)をhttpプロトコルで送ります。

MRTGが動いているマシンでは、ウェブサーバ(Apache)のログに

	target.your.domain - - [18/Apr/2009:21:13:01 +0900]
		"GET /path/to/monitor/?host=target&epoch=1240056781
		&target=smtp&ibytes=123456000&obytes=65432000
		HTTP/1.0" 200 0
こんな情報が残ります。

上の情報を次のスクリプトで処理します。

	#! /bin/sh

	export LANG=C
	export PATH=/usr/bin:/bin:/usr/local/bin:/home/local/bin:/usr/sbin:/sbin

	temp=/tmp/x.$$
	trap 'rm -f $temp*; exit 1' 1 2 15              # clean up files

	logfil=/var/log/http-access

	host=target
	fqdn=target.your.domain
	target="$1"
	url=path/to/monitor/

	grep "^${fqdn} .*${url}?host=${host}.*&target=${target}" $logfil |
        	tail -1 > $temp.1

	tr ' ?&' '\012\012\012' < $temp.1 > $temp.2

	ibytes=`cat $temp.2 | sed -n 's/^ibytes=//p'`
	obytes=`cat $temp.2 | sed -n 's/^obytes=//p'`
	epoch=`cat $temp.2 | sed -n 's/^epoch=//p'`
	stamp=`date -r $epoch '+%Y-%m-%d %H:%M:%S'`

	echo $ibytes
	echo $obytes
	echo $stamp
	echo "${host}-${target}"

	rm -f $temp*
	exit 0
このスクリプトの出力を次のMRTG設定ファイルで処理します。
	#
	# mrtg.cfg -- remote smtp log via http
	#

	WorkDir:	/path/to/work
	HtmlDir:	/path/to/html
	ImageDir:	/path/to/image
	LogDir:		/path/to/log
	IconDir:	/path/to/icon

	#
	# bits       - 得られた値を8倍する (1byte -> 8bits)
	# perminute  - 60倍 (n / sec -> 60n / min)
	#
	# absolute   - 得られた値を間隔(300秒)で割ってグラフ化
	# gauge      - 得られた値をそのままグラフ化
	# 指定なし   - 得られた値と直前の値の差を間隔(300秒)で割ってグラフ化
	#
	# integer    - グラフ下の要約部を整数で表示 (小数点ナシ)
	# withzeroes - ゼロを無視しない
	# nolegend   - 凡例表示しない
	#
	Options[_]: growright,perminute,withzeroes,nopercent,integer,nolegend

	Target[smtp]: `/bin/sh /usr/local/libexec/http2mrtg.sh smtp`
	MaxBytes[smtp]: 12500000
	Title[smtp]: smtp connect/send analysis
	YLegend[smtp]: x1000
	ShortLegend[smtp]: m counts/min
	LegendI[smtp]: smtp connect:
	LegendO[smtp]: status=sent:
	PageTop[smtp]: <H1>SMTP Connect/Send Analysis</H1>

ここで紹介したシェルスクリプトや設定ファイル、マシン名などは、 適当につけたものなので、 みなさんの環境にあわせて、適切にチューニングしてください。


ご質問などありましたらお気軽に