監視に必要な情報は、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 () {
($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);
2回目の実行からユーザとカーネルの合計の使用率とカーネルのみの使用率を返します。返す値は前回の実行からの平均値です。物理メモリの総量と空き容量は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 件のコメント:
コメントを投稿