監視に必要な情報は、Solarisならkstatコマンドでだいたい取得できます。たとえば、aggr1インターフェイスの合計送出バイト数(IF-MIB::ifHCOutOctets)を取得するには、以下のように実行します。
$ kstat aggr:1:aggr1:obytes64 module: aggr instance: 1 name: aggr1 class: net obytes64 448356394356753引数に指定する値はモジュール:インスタンス番号:名前:カウンタ名です。引数なしで実行すると、すべての情報が表示されるので、何を指定すればよいかはだいたいわかります。
kstatコマンドは、kstatデバイスにアクセスするkstatモジュールを使ったPerlスクリプトです。このモジュールを使うと以下のようにPerlで値を取得できます。
$ /usr/bin/perl -le 'use Sun::Solaris::Kstat; > $kstat = Sun::Solaris::Kstat->new(); > print $kstat->{aggr}{1}{aggr1}{obytes64};' 448553825756655
5分間と15分間のロードアベレージは、unix:0:system_misc:avenrun_{5min,15min}を256で割った値です。MRTGでは100倍された値を使うので2.56で割ります。以下のスクリプトをMRTGのターゲットに指定すればSNMPの代わりになります。
#!/usr/bin/perl use strict; use Sun::Solaris::Kstat; use Sys::Hostname; my $kstat = Sun::Solaris::Kstat->new(); my $results = $kstat->{unix}{0}{system_misc}; # make uptime my $uptimedata = `uptime`; $uptimedata =~ /up\s+(\S+.*),\s+\d+\s+user.*load average:\s(\S+.*)$/; my $uptime = $1; # print data printf("%.0f\n", $results->{avenrun_5min} / 2.56); printf("%.0f\n", $results->{avenrun_15min} / 2.56); print "$uptime\n"; print hostname, "\n"; exit(0);
筐体ごとのディスクI/Oの集計は、SNMPのときはターゲットにOIDをずらずらと並べていたのですが、kstatモジュールを使ったスクリプトを呼ぶようにしたらすっきりしました。
Target[ftp.jaist.ac.jp_diskio_sas1]: `/opt/.../bin/mrtg_diskio.pl sd 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29`mrtg_diskio.plはこんな感じです。
#!/usr/bin/perl use strict; use Sun::Solaris::Kstat; use Sys::Hostname; use Math::BigInt; my $kstat = Sun::Solaris::Kstat->new(); my $read = Math::BigInt->new(); my $write = Math::BigInt->new(); my $device = shift(@ARGV); foreach (@ARGV) { my $results = $kstat->{$device}{$_}{"$device$_"}; $read += $results->{nread}; $write += $results->{nwritten}; } # make uptime my $uptimedata = `uptime`; $uptimedata =~ /up\s+(\S+.*),\s+\d+\s+user.*load average:\s(\S+.*)$/; my $uptime = $1; # print data print "$read\n"; print "$write\n"; print "$uptime\n"; print hostname, "\n"; exit(0);
論理CPU32個の使用率の平均は、ティックの差分を取る必要があるので少し面倒ですが、こんな感じです。
#!/usr/bin/perl use strict; use Sun::Solaris::Kstat; use Sys::Hostname; my $log = "/tmp/cpu.log"; my $cpus = 32; my %prev; if (open(PREV, '<', $log)) { my $i = 0; while (2回目の実行からユーザとカーネルの合計の使用率とカーネルのみの使用率を返します。返す値は前回の実行からの平均値です。) { ($prev{idle}[$i], $prev{kernel}[$i], $prev{user}[$i]) = /(\d+) (\d+) (\d+)/; $i++ } close(PREV); } my $kstat = Sun::Solaris::Kstat->new(); my %cur; my %total; for (my $i = 0; $i < $cpus; $i++) { my $results = $kstat->{cpu}{$i}{sys}; foreach ("idle", "kernel", "user") { $cur{$_}[$i] = $results->{"cpu_ticks_$_"}; $total{$_} += &ull_delta($prev{$_}[$i], $cur{$_}[$i]) if %prev; } } sub ull_delta { my ($old, $new) = @_; if ($new >= $old) { return $new - $old; } else { return (18446744073709551615 - $old) + $new + 1; } } if (open(PREV, '>', $log)) { for (my $i = 0; $i < $cpus; $i++) { print PREV join(" ", $cur{idle}[$i], $cur{kernel}[$i], $cur{user}[$i]) ."\n"; } close(PREV); } my $usage; my $kernel; if (%prev) { my $total_ticks = $total{user} + $total{kernel} + $total{idle}; $usage = 100 * ($total{user} + $total{kernel}) / $total_ticks; $kernel = 100 * $total{kernel} / $total_ticks; } # make uptime my $uptimedata = `uptime`; $uptimedata =~ /up\s+(\S+.*),\s+\d+\s+user.*load average:\s(\S+.*)$/; my $uptime = $1; # print datas if (%prev) { printf("%.0f\n", $usage); printf("%.0f\n", $kernel); } else { print("UNKNOWN\n"); print("UNKNOWN\n"); } print "$uptime\n"; print hostname ."\n"; exit(0);
物理メモリの総量と空き容量はunix:0:system_pages:{physmem,freemem}です。単位はページなので、SNMPで得られる値に合わせるには、pagesizeコマンドで求めた1ページのバイト数を掛けて1024で割ります。スワップの情報はSNMPと同じものをkstatで得ることはできません。ftp.jaist.ac.jpにはスワップがないので問題ありませんが、必要ならswap -lで表示される情報を元に計算できます。
こうしてlocalhostのSNMPを指定していたMRTGのターゲットを、すべてスクリプトに置き換えた結果、snmpdは要らなくなったので止めてしまいました。ただこの方法ですと、MRTGが実行されるたびに何度もperlが実行されたり、kstatデバイスがオープンされたりして効率が悪いので、いずれ改善したいと思っています。
0 件のコメント:
コメントを投稿