トップ «前の日(09-29) 最新 次の日(10-01)» 追記

Pyon's Diary

[はてなブックマーク登録数] [Google に登録] [RSS フィード] Gourmet Hardware Programming Society Software
Amazon
成る可くJIS X 0213:2004對應MSフォント(5.0)、IPAフォント(003.02)で御覽下さい

2002-09-30 舊 平成拾肆年葉月廿肆日 (曇) []

[節] 嗚呼、

さうですか、僕も土曜日の酒が抜けてゐません*1

Tags: None | del.icio.usに追加 | はてなブックマークに追加 | livedoor クリップに追加 | Yahoo! ブックマークに追加 | Google ブックマークに追加 | Permalink

*1 其之内絶對酒で失敗するな、自分。つ〜か既に失敗してるか。

[節] 晩御飯。

  • 巻繊汁。
  • 菠薐草のお浸し。
  • 焼賣。
Tags: None | del.icio.usに追加 | はてなブックマークに追加 | livedoor クリップに追加 | Yahoo! ブックマークに追加 | Google ブックマークに追加 | Permalink
本日のツッコミ(全1件) [ツッコミを入れる]

[ツ] こ○ばえ [さぁ,台風パーティーで酒が飲めるぞ〜.]


2003-09-30 舊 平成拾伍年長月伍日 (晴) []

[節] 拾貳國記 風の萬里 黎明の空(上)/拾貳國記 風の萬里 黎明の空(下)/拾貳國記 圖南の翼/拾貳國記 黄昏の岸 暁の天(上)/拾貳國記 黄昏の岸 暁の天(下)

拾貳國記 黄昏の岸 暁の天(下) 拾貳國記 黄昏の岸 暁の天(上) 拾貳國記 圖南の翼 拾貳國記 風の萬里 黎明の空(下) 拾貳國記 風の萬里 黎明の空(上) きのふに引續いて、

を讀んだ。

何だかんだ言つて讀んでゐるなあ。

追記: 續きが出無い。(2007-09-30)

仲々續きが出無い。

此乃人も田中芳樹と同じか。

つて云ふか田中芳樹も「野望圓舞曲」を書いてゐる暇が有るなら、「アルスラーン」、「タイタニア」と「自轉地球儀」の續きを早く書け。

もう何年*1待つてゐると思つてゐるんだ。

既刊リスト觀たらパッケージ變はつてゐるし。

Tags: Books | del.icio.usに追加 | はてなブックマークに追加 | livedoor クリップに追加 | Yahoo! ブックマークに追加 | Google ブックマークに追加 | Permalink

*1 少なく共拾年近く待つてる筈。


2004-09-30 舊 平成拾陸年葉月拾漆日 []

[節] 徹夜決定。

ほへ。

Tags: None | del.icio.usに追加 | はてなブックマークに追加 | livedoor クリップに追加 | Yahoo! ブックマークに追加 | Google ブックマークに追加 | Permalink

2005-09-30 舊 平成拾漆年葉月廿漆日 (金・晴) []

[節] やまし田 (神田)

何と無くやるきが失せたので、つ○いさんと、りょー○ゃんと、そ○ぽ○とで神田のやまし田に行つて、レバ刺し、茹でタン、タン刺し、其之他諸々を食べて飲んで歸つて來た。

Tags: Gourmet | del.icio.usに追加 | はてなブックマークに追加 | livedoor クリップに追加 | Yahoo! ブックマークに追加 | Google ブックマークに追加 | Permalink

2006-09-30 舊 平成拾捌年葉月玖日 (土・晴) []

[節] emerge に要した時間を調べる。

Gentoo/tips -- Gentooメモみたいなページに依ると二つのコマンドが在るらしい。

  • app-portage/splat
  • app-portage/genlop

into the Linux world -- 非力マシン対決(笑)に依ると、genlop の方が簡単に使用出来るらしいので、此方を入れた。

Tags: Gentoo | del.icio.usに追加 | はてなブックマークに追加 | livedoor クリップに追加 | Yahoo! ブックマークに追加 | Google ブックマークに追加 | Permalink

[節] 上野恩賜公園。

けふは、ち○し○がパスポートを買ひたいと行つてゐたので、二人で上野恩賜公園に在る國立博物館(の前の販賣所)に行った。

結構暑かつた。炊き出しの待ち行列が長かった。

憂國の人が訓練をしてゐた。

公園が思つたより廣くて結構歩き回つて仕舞つた。

Tags: Date | del.icio.usに追加 | はてなブックマークに追加 | livedoor クリップに追加 | Yahoo! ブックマークに追加 | Google ブックマークに追加 | Permalink

[節] 晩御飯。

  • 近所の中華料理屋。
Tags: None | del.icio.usに追加 | はてなブックマークに追加 | livedoor クリップに追加 | Yahoo! ブックマークに追加 | Google ブックマークに追加 | Permalink

2007-09-30 舊 平成拾玖年丁亥葉月廿日丁卯 (日・雨) []

[節] 寒い。

行き成り氣温が下がつた。

「暑さ寒さも彼岸迄。」とは云へ急過ぎ無いだろうか。

Tags: None | del.icio.usに追加 | はてなブックマークに追加 | livedoor クリップに追加 | Yahoo! ブックマークに追加 | Google ブックマークに追加 | Permalink

[節] 晩御飯。

  • 燒き立てトースト。
  • 二日目のロール・キャベツ*1
Tags: None | del.icio.usに追加 | はてなブックマークに追加 | livedoor クリップに追加 | Yahoo! ブックマークに追加 | Google ブックマークに追加 | Permalink

*1 二日目は旨い。

[節] 捏造された聖書

捏造された聖書 捏造された聖書 を讀んだ。

原題は「MISQUOTING JESUS」自分の英語力では「イエスを誤引用する。」か。

其れは兎も角、面白かつたので一氣に讀んで仕舞つた。讀み終はつたら朝の八時だつた。

追記: 聖書のみ。(2007-10-01)

著者の「バート・D・アーマン」(Bart D. EHRMAN) は、Google で「捏造された聖書」を檢索すると「本文批評學」で有名な學者らしい。

「本文批評」とは Wikipedia に據ると、

本文批評 (ほんもんひひゃう、英: Textual citicism, 獨: Textkritik, 佛: Critique textuelle) とは、文獻學において、ある文書の現存する寫本から、可能な限り、その文書の元來の形を復元する作業を言ふ。本文批判、正文批判(批評)、テキスト批判(批評)とも呼ばれる。

[Wikipedia - 本文批評より引用]

との事。要するに「今は無き原本を復元する」と云ふ事らしいのだが、著者は「聖書の原本を復元する」専門家らしい。

何故「聖書の原本を復元する」事が重要かと云ふと、昔は活版印刷も無く書籍の配布は寫本に據るしか無かつた。寫本は人が手で一文字づゝ、一単語づゝ書き寫して行くので、其乃際に誤字・脱字等の寫し間違ひが有つたり、書き寫す人が「此は間違ひだろう」と判斷して(善意又は悪意の)改竄が爲される事が有る。其乃爲、寫本が行はれる度に原本から懸け離れて行く。

普通の文書なら「さう云ふ事も有るさ」で濟む事も有るかも知れ無いが、ものが聖書だと然うは行か無い。何故ならば、

聖書は無謬なる神の御言葉である

[捏造された聖書 P.11より引用]

だから。途中で人の手に據つて誤字・脱字・書換が行はれてゐると問題と成る。其乃割には米國での報道とかを見る限り一般の信者では餘り問題に成つてゐ無いみたいだが。

此乃本は、聖書の歴史、寫本の問題、聖書本文批評の歴史と其乃方法の歴史、が判り易く且つ讀み易く書いて在り、聖書に關して大した予備知識が無くても充分讀める。聖書に興味が或る人には御奨めの本だと思ふ。

Tags: Books | del.icio.usに追加 | はてなブックマークに追加 | livedoor クリップに追加 | Yahoo! ブックマークに追加 | Google ブックマークに追加 | Permalink

2008-09-30 舊 平成廿年戊子長月貳日癸酉 (火・雨) []

[節] 晩御飯。

  • 押麥飯。
  • 小葱の味噌汁。
  • 挽肉と茄子と甘藍の餡掛け炒め。
  • 豚御飯。(きのふの)
Tags: None | del.icio.usに追加 | はてなブックマークに追加 | livedoor クリップに追加 | Yahoo! ブックマークに追加 | Google ブックマークに追加 | Permalink

[節] KURO-BOX/PRO (No.42) RRDtoolで温度・其乃外を監視する。

先日S.M.A.R.T.でKURO-BOX/PROのHDDの温度を取得出來る樣に成つたので、序でにRRDtoolでグラフを描かせる事にした。

參考にした頁は以下の通り。

 * {{tlink "http://agj.at/~fors/sysworks/data/rrdtool/rrdtool.txt", "rrdtool - ラウンドロビンデータベースツール"}}。({{tlink "http://s01.megalodon.jp/2008-0930-2301-25/agj.at/~fors/sysworks/data/rrdtool/rrdtool.txt", "ウェブ魚拓", "rrdtool - ラウンドロビンデータベースツール"}})
 * {{tlink "http://agj.at/~fors/sysworks/data/rrdtool/rrdcreate.txt", "rrdtool create - 新しいラウンドロビンデータベースを作成します"}}。({{tlink "http://s03.megalodon.jp/2008-0930-2303-23/agj.at/~fors/sysworks/data/rrdtool/rrdcreate.txt", "ウェブ魚拓", "rrdtool create - 新しいラウンドロビンデータベースを作成します"}})
 * {{tlink "http://agj.at/~fors/sysworks/data/rrdtool/rrdupdate.txt", "rrdtool update - 新しい値をRRDに格納します"}}。({{tlink "http://s01.megalodon.jp/2008-0930-2304-55/agj.at/~fors/sysworks/data/rrdtool/rrdupdate.txt", "ウェブ魚拓", "rrdtool update - 新しい値をRRDに格納します"}})
 * {{tlink "http://agj.at/~fors/sysworks/data/rrdtool/rrdgraph.txt", "rrdtool graph - 1つもしくは複數のRRDを元にグラフを生成します"}}。({{tlink "http://s04.megalodon.jp/2008-0930-2306-49/agj.at/~fors/sysworks/data/rrdtool/rrdgraph.txt", "ウェブ魚拓", "rrdtool graph - 1つもしくは複數のRRDを元にグラフを生成します"}})
 * {{tlink "http://agj.at/~fors/sysworks/data/rrdtool/rrdtune.txt", "rrdtune - ラウンドロビンデータベースのいくつかの基本的な屬性を變更します"}}。({{tlink "http://s01.megalodon.jp/2008-0930-2311-23/agj.at/~fors/sysworks/data/rrdtool/rrdtune.txt", "ウェブ魚拓", "rrdtune - ラウンドロビンデータベースのいくつかの基本的な屬性を變更します"}})
 * {{tlink "http://agj.at/~fors/sysworks/data/rrdtool/rrdinfo.txt", "rrdinfo - RRDからヘッダ情報を抽出します"}}。({{tlink "http://s01.megalodon.jp/2008-0930-2317-00/agj.at/~fors/sysworks/data/rrdtool/rrdinfo.txt", "ウェブ魚拓", "rrdinfo - RRDからヘッダ情報を抽出します"}})

取敢へずRRDtoolを入れた。Debianなので簡單に入つた。

# /usr/bin/aptitude install rrdtool
Reading package lists... Done
Building dependency tree
Reading state information... Done
Reading extended state information
Initializing package states... Done
The following NEW packages will be installed:
  defoma{a} fontconfig{a} fontconfig-config{a} libcairo2{a} libdatrie0{a} libfontconfig1{a}
  libfontenc1{a} libfreetype6{a} libglib2.0-0{a} libglib2.0-data{a} libpango1.0-0{a}
  libpango1.0-common{a} libpixman-1-0{a} libpng12-0{a} librrd4{a} libthai-data{a} libthai0{a}
  libxcb-render-util0{a} libxcb-render0{a} libxfont1{a} libxft2{a} libxrender1{a} rrdtool
  ttf-dejavu{a} ttf-dejavu-core{a} ttf-dejavu-extra{a} x-ttcidfont-conf{a} x11-common{a}
  xfonts-encodings{a} xfonts-utils{a}
0 packages upgraded, 30 newly installed, 0 to remove and 21 not upgraded.
Need to get 10.5MB of archives. After unpacking 23.3MB will be used.
Do you want to continue? [Y/n/?]
(中略)
Reading extended state information
Initializing package states... Done
Writing extended state information... Done

矢鱈と澤山グラフィック關係のパッケージが入つた。

次にRRDファイルを作成した。温度なので手引きに書いて在る事を其乃儘利用した。但し今囘はmiconaplで取得出來る温度とsmartctlで取得出來る温度の二つを記録出來る樣にした。

#!/bin/sh
rrdtool create \
	/var/lib/rrdtool/temperature.rrd \
	--step 300 \
	DS:HDD:GAUGE:600:-273:5000 \
	DS:BOX:GAUGE:600:-273:5000 \
	RRA:AVERAGE:0.5:12:35064 \
	RRA:MIN:0.5:12:35064 \
	RRA:MAX:0.5:12:35064 \
	RRA:LAST:0.5:1:420768

データソース「HDD」はsmartctlで取得出來るHDDの温度を、データソース「BOX」はmiconaplで取得出來る温度を格納する。

データ數は基本5分(300秒)に1個で4年分を貯める事にしたので「RRA:LAST」は

1440 / 5 * ( 4 * 365 + 1) = 420768

で420,768個。最小値(MIN)、最大値(MAX)、平均(AVERAGE)は1時間(5 * 12)内の最小、最大、平均を4年分格納するので、

420768 / 12 = 35064

で35,064個とした。

次にデータを取得してRRDを更新するスクリプトを作つた。其乃スクリプトではデータの更新を行つた後で序でにグラフ(畫像)も生成する事にした。

#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use Carp;
use Getopt::Long;
use IO::Pipe;
use Readonly;

Readonly::Scalar my $day_sec => 24 * 60 * 60;
Readonly::Scalar my $rrd     => q{/var/lib/rrdtool/temperature.rrd};
Readonly::Array my @types    => qw(day week month year);
Readonly::Hash my %span      => {
    'day'   => -86400,
    'week'  => -86400 * 7,
    'month' => -86400 * 31,
    'year'  => -86400 * 365,
};
Readonly::Hash my %fmrts => {
    'pngfile' => q{/var/www/status/temperature.%s.png},
    'updcmd'  => q{/usr/bin/rrdtool update %s N:%d:%d},
    'grpcmd'  => <<'_GRAPH_CMD_', };
/usr/bin/rrdtool graph %s \
    --start %s \
    --width 480 \
    --vertical-label "Temperature (C)" \
    --title "HDD / Box Temperature (%s)" \
    DEF:hdd=%s:HDD:LAST \
    DEF:box=%s:BOX:LAST \
    LINE2:hdd#ff0000:"HDD" \
    GPRINT:hdd:LAST:"Cur. %%6.2lfC," \
    GPRINT:hdd:MIN:"Min. %%6.2lfC," \
    GPRINT:hdd:MAX:"Max. %%6.2lfC," \
    GPRINT:hdd:AVERAGE:"Ave. %%6.2lfC\n" \
    LINE2:box#ff8000:"BOX" \
    GPRINT:box:LAST:"Cur. %%6.2lfC," \
    GPRINT:box:MIN:"Min. %%6.2lfC," \
    GPRINT:box:MAX:"Max. %%6.2lfC," \
    GPRINT:box:AVERAGE:"Ave. %%6.2lfC\n" \
    > /dev/null 2>&1
_GRAPH_CMD_

# ヘルプを表示する。
sub help {
    print <<'_HELP_';
usage;

  rrdupdate.temperature.pl [--help] [--only-fetch] [--only-graph]

    --help       : display help and exit.
    --only-fetch : Only fetch data.
    --only-graph : Only draw graph.

_HELP_
    exit 0;
}

my %opts = (
    'debug'      => 0,
    'help'       => 0,
    'fetch-data' => 1,
    'draw-graph' => 1,
);

# コマンドライン・オプションを解析する。
{
    GetOptions(
        'debug'       => \$opts{'debug'},
        'help'        => \$opts{'help'},
        'only-fetch!' => \$opts{'draw-graph'},
        'only-graph!' => \$opts{'fetch-data'},
    ) or exit 1;
    $opts{'help'} and help;
}

# データを取得してRRDを更新する。
if ( $opts{'fetch-data'} ) {
    my %temperature = ( 'hdd' => 0, 'box' => 0, );

    # HDDの温度を取得する。
    {
        my $pipe = IO::Pipe->new;
        $pipe->reader(qw(/usr/sbin/smartctl --attributes /dev/sda));
        while (<$pipe>) {
            m/\A194 Temperature_Celsius\s+/ or next;
            $temperature{'hdd'} = ( split /\s+/, $_ )[9];
        }
        $temperature{'hdd'} or croak q{Can't get temperature of hdd.};
    }

    # 筐體の温度を取得する。
    {
        my $pipe = IO::Pipe->new;
        $pipe->reader(qw(/usr/local/sbin/miconapl -a temp_get));
        while (<$pipe>) {
            m/\Atemp=/ or next;
            $temperature{'box'} = ( split /=/, $_ )[1];
        }
        $temperature{'box'} or croak q{Can't get temperature of box.};
    }

    my $update = sprintf $fmrts{'updcmd'}, $rrd, $temperature{'hdd'},
      $temperature{'box'};

    $opts{'debug'} and carp Dumper( \$update );

    system($update) == 0 or die "system $update failed: $?";
}

# グラフを描く。
if ( $opts{'draw-graph'} ) {
    foreach my $type (@types) {
        my $png = sprintf $fmrts{'pngfile'}, $type;
        my $graph = sprintf $fmrts{'grpcmd'}, $png, $span{$type}, $type, $rrd,
          $rrd;

        $opts{'debug'} and carp Dumper( \$graph );

        system($graph) == 0 or die "system $graph failed: $?";
    }
}

此れをcronで5分に1囘實行する樣に設定した。

暫く回して得られたグラフが下の畫像。

KURO-BOX/PROの温度變化。(例)

普段は大體40度前後だがsmartctlでテストを實行すると途端に温度が上がつた。

追記: モジュール。

PerlからRRDを扱ふのに、

等のモジュールが在るみたいなので、上のスクリプトは其乃内書き直す事。

追記: RRDsを使つてみた。(2008-10-01)

RRDsPerlから共有ライブラリ経由でRRDを扱ふ爲のモジュール。RRDの更新とグラフの描畫を此乃モジュールを使つて行ふ樣に直した。

#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use Carp;
use Data::Dumper;
use Getopt::Long;
use IO::Pipe;
use RRDs;
use Readonly;

Readonly::Scalar my $rrd  => q{/var/lib/rrdtool/temperature.rrd};
Readonly::Array my @types => qw(day week month year);
Readonly::Hash my %span   => {
    'day'   => -86400,
    'week'  => -86400 * 7,
    'month' => -86400 * 31,
    'year'  => -86400 * 365,
};
Readonly::Hash my %fmrts =>
    { 'pngfile' => q{/var/www/status/temperature.%s.png}, };

# ヘルプを表示する。
sub help {
    print <<'_HELP_';
usage;

  rrdupdate.temperature.pl [--help] [--noupdating] [--nodrawing]

    --help        : display help and exit.
    --noupdating : doesn't update rrd.
    --nodrawing  : doesn't draw graph.

_HELP_
    exit 0;
}

my %opts = (
    'debug'    => 0,
    'help'     => 0,
    'updating' => 1,
    'drawing'  => 1,
);

# コマンドライン・オプションを解析する。
{
    GetOptions(
        'debug'     => \$opts{'debug'},
        'help'      => \$opts{'help'},
        'updating!' => \$opts{'updating'},
        'drawing!'  => \$opts{'drawing'},
    ) or exit 1;
    $opts{'help'}  and help;
    $opts{'debug'} and print Dumper( \%opts );
}

# データを取得してRRDを更新する。
if ( $opts{'updating'} ) {

    # HDDの温度を取得する。
    my $hddtemp;
    {
        my $pipe = IO::Pipe->new;
        $pipe->reader(qw(/usr/sbin/smartctl --attributes /dev/sda));
        while (<$pipe>) {
            s/\A\s+//;
            s/\s+\Z//;
            m/\A194 Temperature_Celsius\s+/ or next;
            $hddtemp = ( split /\s+/, $_ )[9];
            last;
        }
        $hddtemp or croak q{Can't get temperature of hdd.};
    }

    # 筐體の温度を取得する。
    my $boxtemp;
    {
        my $pipe = IO::Pipe->new;
        $pipe->reader(qw(/usr/local/sbin/miconapl -a temp_get));
        while (<$pipe>) {
            s/\A\s+//;
            s/\s+\Z//;
            m/\Atemp=/ or next;
            $boxtemp = ( split /=/, $_ )[1];
            last;
        }
        $boxtemp or croak q{Can't get temperature of box.};
    }

    # RRDを更新する。
    RRDs::update( $rrd, "N:$hddtemp:$boxtemp" );
    if ( my $err = RRDs::error ) {
        croak "ERROR while updating $rrd: $err";
    }
}

# グラフを描く。
if ( $opts{'drawing'} ) {
    foreach my $type (@types) {
        my $png = sprintf $fmrts{'pngfile'}, $type;
        my $span = $span{$type};

        my ( $averages, $xsize, $ysize ) = RRDs::graph(
            $png,
            '--start',
            $span,
            '--width',
            '480',
            '--vertical-label',
            'Temperature (C)',
            '--title',
            "HDD / Box Temperature ($type)",
            "DEF:hdd=$rrd:HDD:LAST",
            "DEF:box=$rrd:BOX:LAST",
            q{LINE2:hdd#ff0000:HDD},
            q{GPRINT:hdd:LAST:Cur. %6.2lfC,},
            q{GPRINT:hdd:MIN:Min. %6.2lfC,},
            q{GPRINT:hdd:MAX:Max. %6.2lfC,},
            q{GPRINT:hdd:AVERAGE:Ave. %6.2lfC\n},
            q{LINE2:box#ff8000:BOX},
            q{GPRINT:box:LAST:Cur. %6.2lfC,},
            q{GPRINT:box:MIN:Min. %6.2lfC,},
            q{GPRINT:box:MAX:Max. %6.2lfC,},
            q{GPRINT:box:AVERAGE:Ave. %6.2lfC\n},
        );
        if ( my $err = RRDs::error ) {
            croak "ERROR while drawing $png: $err";
        }
        if ( $opts{'debug'} ) {
            print "Imagesize: ${xsize}x${ysize}\n";
            print "Averages: ", ( join ", ", @{$averages} ), "\n";
        }
    }
}

追記: CPU利用率を監視する。(2008-10-01)

序でにCPU利用率も監視してグラフを生成させる事にした。CPU使用時間は/proc/statから得られた。

# /bin/cat /proc/stat
cpu  3516697 2432459 1133790 17817467 158719 15583 67406 0 0
cpu0 3516697 2432459 1133790 17817467 158719 15583 67406 0 0
(省略)

九つの數字の意味は「man 5 proc」に書いて在つた。

  • ユーザモードでの使用時間。
  • 低優先度(nice)ユーザモードでの使用時間。
  • システムモードでの使用時間。
  • アイドル時間。
  • I/O待ち時間。(2.5.41から)
  • 割込みに(IRQ)取られた時間。(2.6.0-test4から)
  • ソフトウェア割込み(?)に取られた時間。(2.6.0-test4から)
  • 假想環境でのOSに取られた時間(?)。(2.6.11から)
  • ゲストOSの假想CPUに取られた時間(?)。(2.6.24から)

最後の二つは餘り關係無さゝうだつたが一應取る事にした。以下の樣なシェルスクリプトでRRDを作成した。

#!/bin/sh
for c in cpu cpu0
do
	rrdtool create \
		/var/lib/rrdtool/$c.rrd \
		--step 300 \
		DS:USER:DERIVE:1200:U:U \
		DS:NICE:DERIVE:1200:U:U \
		DS:SYSTEM:DERIVE:1200:U:U \
		DS:IDLE:DERIVE:1200:U:U \
		DS:IOWAIT:DERIVE:1200:U:U \
		DS:IRQ:DERIVE:1200:U:U \
		DS:SOFTIRQ:DERIVE:1200:U:U \
		DS:STEAL:DERIVE:1200:U:U \
		DS:GUEST:DERIVE:1200:U:U \
		RRA:AVERAGE:0.5:12:35064 \
		RRA:MIN:0.5:12:35064 \
		RRA:MAX:0.5:12:35064 \
		RRA:LAST:0.5:1:420768
done

データを取得してグラフを生成するスクリプトは以下の樣にした。

#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use Carp;
use Getopt::Long;
use IO::File;
use RRDs;
use Readonly;

Readonly my $proc_file => q{/proc/stat};
Readonly my %span      => {
    'day'   => 86400 * -1,
    'week'  => 86400 * -7,
    'month' => 86400 * -31,
    'year'  => 86400 * -366,
};
Readonly my $rrddir => q{/var/lib/rrdtool};
Readonly my $pngdir => q{/var/www/status};
Readonly my %rrd    => {
    'cpu'  => qq{$rrddir/cpu.rrd},
    'cpu0' => qq{$rrddir/cpu0.rrd},
};
Readonly my %png => {
    'cpu' => {
        'day'   => qq{$pngdir/cpu.day.png},
        'week'  => qq{$pngdir/cpu.week.png},
        'month' => qq{$pngdir/cpu.month.png},
        'year'  => qq{$pngdir/cpu.year.png},
    },
    'cpu0' => {
        'day'   => qq{$pngdir/cpu0.day.png},
        'week'  => qq{$pngdir/cpu0.week.png},
        'month' => qq{$pngdir/cpu0.month.png},
        'year'  => qq{$pngdir/cpu0.year.png},
    },
};

# ヘルプを表示する。
sub help {
    print <<'_HELP_';
usage;

  rrdupdate.cpu.pl [--help] [--noupdating] [--nodrawing]

    --help       : display help and exit.
    --noupdating : doesn't update rrd.
    --nodrawing  : doesn't draw graph.

_HELP_
    exit 0;
}

my %opts = (
    'debug'    => 0,
    'help'     => 0,
    'updating' => 1,
    'drawing'  => 1,
);

# コマンドライン・オプションを解析する。
{
    GetOptions(
        'debug'     => \$opts{'debug'},
        'help'      => \$opts{'help'},
        'updating!' => \$opts{'updating'},
        'drawing!'  => \$opts{'drawing'},
    ) or exit 1;

    $opts{'help'} and help;
}

# データを取得してRRDを更新する。
if ( $opts{'updating'} ) {
    my $fh = IO::File->new( $proc_file, 'r' ) or croak $!;
    while (<$fh>) {
        s/\A\s+//;
        s/\s+\Z//;
        m/\A(cpu0?)\s+/ or next;
        my ( $cpu, @data ) = split /\s+/, $_;

        # RRDを更新する。
        RRDs::update( $rrd{$cpu}, join ':', 'N', @data );
        if ( my $err = RRDs::error ) {
            croak 'ERROR while updating ' . $rrd{$cpu} . ': ' . $err;
        }
    }
    $fh->close;
}

# グラフを描く。
if ( $opts{'drawing'} ) {
    foreach my $cpu ( keys %png ) {
        foreach my $type ( keys %{ $png{$cpu} } ) {
            my $rrd   = $rrd{$cpu};
            my $png   = $png{$cpu}{$type};
            my $start = $span{$type};
            my ( $averages, $xsize, $ysize ) = RRDs::graph(
                $png,
                qq{--start=$start},
                q{--width=480},
                q{--vertical-label=ratio (%)},
                qq{--title=$cpu usage ($type)},
                qq{DEF:user=$rrd:USER:LAST},
                qq{DEF:nice=$rrd:NICE:LAST},
                qq{DEF:system=$rrd:SYSTEM:LAST},
                qq{DEF:idle=$rrd:IDLE:LAST},
                qq{DEF:iowait=$rrd:IOWAIT:LAST},
                qq{DEF:irq=$rrd:IRQ:LAST},
                qq{DEF:softirq=$rrd:SOFTIRQ:LAST},
                qq{DEF:steal=$rrd:STEAL:LAST},
                qq{DEF:guest=$rrd:GUEST:LAST},
                q{AREA:user#ff0000:User    },
                q{GPRINT:user:LAST:Cur. %6.2lf%%,},
                q{GPRINT:user:MIN:Min. %6.2lf%%,},
                q{GPRINT:user:MAX:Max. %6.2lf%%,},
                q{GPRINT:user:AVERAGE:Ave. %6.2lf%%\n},
                q{STACK:nice#ff8000:Nice    },
                q{GPRINT:nice:LAST:Cur. %6.2lf%%,},
                q{GPRINT:nice:MIN:Min. %6.2lf%%,},
                q{GPRINT:nice:MAX:Max. %6.2lf%%,},
                q{GPRINT:nice:AVERAGE:Ave. %6.2lf%%\n},
                q{STACK:system#ffff00:System  },
                q{GPRINT:system:LAST:Cur. %6.2lf%%,},
                q{GPRINT:system:MIN:Min. %6.2lf%%,},
                q{GPRINT:system:MAX:Max. %6.2lf%%,},
                q{GPRINT:system:AVERAGE:Ave. %6.2lf%%\n},
                q{STACK:iowait#00ff00:I/O Wait},
                q{GPRINT:iowait:LAST:Cur. %6.2lf%%,},
                q{GPRINT:iowait:MIN:Min. %6.2lf%%,},
                q{GPRINT:iowait:MAX:Max. %6.2lf%%,},
                q{GPRINT:iowait:AVERAGE:Ave. %6.2lf%%\n},
                q{STACK:irq#00ff80:IRQ     },
                q{GPRINT:irq:LAST:Cur. %6.2lf%%,},
                q{GPRINT:irq:MIN:Min. %6.2lf%%,},
                q{GPRINT:irq:MAX:Max. %6.2lf%%,},
                q{GPRINT:irq:AVERAGE:Ave. %6.2lf%%\n},
                q{STACK:softirq#00ffff:Soft IRQ},
                q{GPRINT:softirq:LAST:Cur. %6.2lf%%,},
                q{GPRINT:softirq:MIN:Min. %6.2lf%%,},
                q{GPRINT:softirq:MAX:Max. %6.2lf%%,},
                q{GPRINT:softirq:AVERAGE:Ave. %6.2lf%%\n},
                q{STACK:steal#0080ff:Steal   },
                q{GPRINT:steal:LAST:Cur. %6.2lf%%,},
                q{GPRINT:steal:MIN:Min. %6.2lf%%,},
                q{GPRINT:steal:MAX:Max. %6.2lf%%,},
                q{GPRINT:steal:AVERAGE:Ave. %6.2lf%%\n},
                q{STACK:guest#0000ff:Guest   },
                q{GPRINT:guest:LAST:Cur. %6.2lf%%,},
                q{GPRINT:guest:MIN:Min. %6.2lf%%,},
                q{GPRINT:guest:MAX:Max. %6.2lf%%,},
                q{GPRINT:guest:AVERAGE:Ave. %6.2lf%%\n},
                q{STACK:idle#F0F0F0:Idle    },
                q{GPRINT:idle:LAST:Cur. %6.2lf%%,},
                q{GPRINT:idle:MIN:Min. %6.2lf%%,},
                q{GPRINT:idle:MAX:Max. %6.2lf%%,},
                q{GPRINT:idle:AVERAGE:Ave. %6.2lf%%\n},
            );

            if ( my $err = RRDs::error ) {
                croak q{ERROR while drawing } . $png . q{: } . $err;
            }
            if ( $opts{'debug'} ) {
                print "Imagesize: ${xsize}x${ysize}\n";
                print "Averages: ", ( join ", ", @{$averages} ), "\n";
            }
        }
    }
}

此乃スクリプトを5分毎にcronで實行する樣に設定した。

暫く待つてから生成されたグラフは以下の通り。

全CPUの使用率。(例)
CPU 0の使用率。(例)

CPU利用率、温度、ディスクI/O、ネットワーク・トラフィックのグラフを5分毎に生成させてゐるだけで恆に30%も消費してゐた。

困つた。

追記: データソースタイプを變更した。(2008-10-01)

CPU利用率のRRDはデータソースタイプを總て「DERIVE」にしてゐたのだが、實は其れは間違ひで「COUNTER」にしなければいけない事に氣が付いた。

其處でrrdinfoとrrdtuneとを使用してデータソースタイプを變更してみた。

# /usr/bin/rrdtool info /var/lib/rrdtool/cpu.rrd
filename = "/var/lib/rrdtool/cpu.rrd"
rrd_version = "0003"
step = 300
last_update = 1222870322
ds[USER].type = "DERIVE"
ds[USER].minimal_heartbeat = 1200
(省略)

で判る樣にデータソースタイプは「DERIVE」に成つてゐる。此れを變更した。

# /usr/bin/rrdtool tune /var/lib/rrdtool/cpu.rrd -d USER:COUNTER

を實行してデータソースタイプを變更してから再度確認した。

# /usr/bin/rrdtool info /var/lib/rrdtool/cpu.rrd
filename = "/var/lib/rrdtool/cpu.rrd"
rrd_version = "0003"
step = 300
last_update = 1222870322
ds[USER].type = "COUNTER"
ds[USER].minimal_heartbeat = 1200
(省略)

慥かに「DERIVE」から「COUNTER」に變更された。

追記: ネットワーク・トラフィックを監視する。(2008-10-02)

温度、CPUと來たので次はネットワーク・トラフィックを監視する事にした。ネットワーク・トラフィックは/proc/net/devから得られた。

# /bin/cat /proc/net/dev
Inter-|   Receive                                                |  Transmit
 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
    lo:    4672      46    0    0    0     0          0         0     4672      46    0    0    0     0       0          0
  eth0:4146163939 3220427    0    0    0     0          0         0 221565827  810949    0    0    0     0       0          0

此乃出力の意味はCPU利用率と同じく「man 5 proc」に書いて在つた。

必要なのは1番目と9番目の送受信バイト數、2番目と10番目の送受信パケット數なので、以下の樣なRRDにした。

#!/bin/sh
for i in lo eth0
do
	rrdtool create \
		/var/lib/rrdtool/net.${i}.rrd \
		--step 300 \
		DS:IN:COUNTER:600:U:U \
		DS:OUT:COUNTER:600:U:U \
        DS:IN_PACKET:COUNTER:600:U:U \
        DS:OUT_PACKET:COUNTER:600:U:U \
		RRA:AVERAGE:0.5:12:35064 \
		RRA:MIN:0.5:12:35064 \
		RRA:MAX:0.5:12:35064 \
		RRA:LAST:0.5:1:420768
done

此乃RRDにデータを格納するスクリプトは以下の樣にした。

#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use Carp;
use Data::Dumper;
use Getopt::Long;
use IO::File;
use RRDs;
use Readonly;

Readonly my %span => {
    'day'   => 86400 * -1,
    'week'  => 86400 * -7,
    'month' => 86400 * -31,
    'year'  => 86400 * -366,
};
Readonly my $rrddir => q{/var/lib/rrdtool};
Readonly my $pngdir => q{/var/www/status};
Readonly my %rrd    => {
    'lo'   => qq{$rrddir/net.lo.rrd},
    'eth0' => qq{$rrddir/net.eth0.rrd},
};
Readonly my %png => {
    'lo' => {
        'day'   => qq{$pngdir/net.lo.day.png},
        'week'  => qq{$pngdir/net.lo.week.png},
        'month' => qq{$pngdir/net.lo.month.png},
        'year'  => qq{$pngdir/net.lo.year.png},
    },
    'eth0' => {
        'day'   => qq{$pngdir/net.eth0.day.png},
        'week'  => qq{$pngdir/net.eth0.week.png},
        'month' => qq{$pngdir/net.eth0.month.png},
        'year'  => qq{$pngdir/net.eth0.year.png},
    },
};

sub help {
    print <<'_HELP_';
usage;

  rrdupdate.net.pl [--help] [--noupdating] [--nodrawing]

    --help       : display help and exit.
    --noupdating : doesn't update rrd.
    --nodrawing  : doesn't draw graph.

_HELP_
    exit 0;
}

my %opts = (
    'debug'    => 0,
    'help'     => 0,
    'updating' => 1,
    'drawing'  => 1,
);

# コマンドライン・オプションを解析する。
{
    GetOptions(
        'debug'     => \$opts{'debug'},
        'help'      => \$opts{'help'},
        'updating!' => \$opts{'updating'},
        'drawing!'  => \$opts{'drawing'},
    ) or exit 1;
    $opts{'help'} and help;
}

# データを取得してRRDを更新する。
if ( $opts{'updating'} ) {

    # 送受信データ量とパケット數を取得し、
    # RRDを更新する。
    my $fh = IO::File->new( '/proc/net/dev', 'r' ) or croak $!;
    while (<$fh>) {
        s/\A\s+//;
        s/\s+\Z//;
        m/\A(lo|eth0):/ or next;
        my ( $if, @data ) = split /[:\s]+/, $_;

        RRDs::update( $rrd{$if}, join( ':', q{N}, @data[ 0, 8, 1, 9 ] ) );
        if ( my $err = RRDs::error ) {
            croak q{ERROR while updating } . $rrd{$if} . q{: } . $err;
        }
    }
}

# 日・週・月・年のグラフを描く。
if ( $opts{'drawing'} ) {
    foreach my $interface ( keys %png ) {
        foreach my $type ( keys %{ $png{$interface} } ) {
            my $start = $span{$type};
            my $rrd   = $rrd{$interface};
            my $png   = $png{$interface}{$type};
            my ( $averages, $xsize, $ysize ) = RRDs::graph(
                $png,
                qq{--start=$start},
                q{--width=480},
                q{--vertical-label=Traffic / Packets},
                qq{--title=Traffic / Packets ($interface, $type)},
                qq{DEF:in=$rrd:IN:LAST},
                qq{DEF:out=$rrd:OUT:LAST},
                qq{DEF:in_packet=$rrd:IN_PACKET:LAST},
                qq{DEF:out_packet=$rrd:OUT_PACKET:LAST},
                q{CDEF:in_c=in},
                q{CDEF:out_c=out,-1,*},
                q{CDEF:in_packet_c=in_packet},
                q{CDEF:out_packet_c=out_packet,-1,*},
                q{AREA:in_c#ff0000:In   },
                q{GPRINT:in_c:LAST:Cur. %+.2le,},
                q{GPRINT:in_c:MIN:Min. %+.2le,},
                q{GPRINT:in_c:MAX:Max. %+.2le,},
                q{GPRINT:in_c:AVERAGE:Ave. %+.2le\n},
                q{LINE2:in_packet_c#ffa0a0:P\:In },
                q{GPRINT:in_packet_c:LAST:Cur. %+.2le,},
                q{GPRINT:in_packet_c:MIN:Min. %+.2le,},
                q{GPRINT:in_packet_c:MAX:Max. %+.2le,},
                q{GPRINT:in_packet_c:AVERAGE:Ave. %+.2le\n},
                q{AREA:out_c#0000ff:Out  },
                q{GPRINT:out_c:LAST:Cur. %+.2le,},
                q{GPRINT:out_c:MIN:Min. %+.2le,},
                q{GPRINT:out_c:MAX:Max. %+.2le,},
                q{GPRINT:out_c:AVERAGE:Ave. %+.2le\n},
                q{LINE2:out_packet_c#a0a0ff:P\:Out},
                q{GPRINT:out_packet_c:LAST:Cur. %+.2le,},
                q{GPRINT:out_packet_c:MIN:Min. %+.2le,},
                q{GPRINT:out_packet_c:MAX:Max. %+.2le,},
                q{GPRINT:out_packet_c:AVERAGE:Ave. %+.2le\n},
            );
            if ( my $err = RRDs::error ) {
                croak "ERROR while drawing $png: $err";
            }
            if ( $opts{'debug'} ) {
                print "Imagesize: ${xsize}x${ysize}\n";
                print "Averages: ", ( join ", ", @{$averages} ), "\n";
            }
        }
    }
}

此乃スクリプトを5分毎にcronで實行する樣に設定して、暫く待つと以下の樣なグラフが得られた。

ループバックのトラフィック。(例)
eth0のトラフィック。(例)

餘りトラフィックは無かつた。もう少しKURO-BOX/PROの活用方法を考へた方が良いかも知れない。


正當なXHTML1.1です! 正當なCSSです! BlogScouter Pyon's Land (MyMiniCity)
© pyon