muninのDisk IOs per deviceからsdaなどを除外する


Linux LVMベースでパーテーションが構成されている環境で、muninを使ったら、Disk IOs per deviceなどで、「sda」が存在していた。

今回の環境だと、sda内に、それ以外のLVMが含まれている形となるので、sda自体を表示する意味がほとんど無いので、除外しようと思う。

資料は「diskstats 」。

「/etc/munin/plugin-conf.d/diskstats」というファイルに下記を記載した。

[diskstats]
env.exclude sda

この変更を行った後は、下記の様なグラフとなった。

CentOS7環境でのmunin/rrdtoolの文字化けはvlgothic-fontsで対処


CentOS7環境でmuninを使ったら、文字化けっぽいものが・・・
何が原因なのかわからなかったので、とりあえず切り分けのために、以前作った「IIJmioクーポンスイッチAPIを使って使用量グラフ作成」のrrdtoolをCentOS7環境で実行してみた

rrdtool graph test-year.png --imgformat=PNG \
--height=300 \
--width=600 \
--lower-limit=0 \
--end now --start end-14months \
--vertical-label "MB" \
--x-grid WEEK:1:MONTH:1:MONTH:1:0:%m/%d \
--units-exponent 0 \
--title="IIJmioの1年分使用量" \
DEF:SIM1C=hdo~.rrd:withCoupon:LAST \
DEF:SIM1N=hdo~.rrd:withoutCoupon:LAST \
DEF:SIM2C=hdo~.rrd:withCoupon:LAST \
DEF:SIM2N=hdo~.rrd:withoutCoupon:LAST \
DEF:SIM3C=hdo~.rrd:withCoupon:LAST \
DEF:SIM3N=hdo~.rrd:withoutCoupon:LAST \
DEF:SIM4C=hdo~.rrd:withCoupon:LAST \
DEF:SIM4N=hdo~.rrd:withoutCoupon:LAST \
DEF:SIM5C=hdo~.rrd:withCoupon:LAST \
DEF:SIM5N=hdo~.rrd:withoutCoupon:LAST \
CDEF:SIM1=SIM1C,SIM1N,+ \
CDEF:SIM2=SIM2C,SIM2N,+ \
CDEF:SIM3=SIM3C,SIM3N,+ \
CDEF:SIM4=SIM4C,SIM4N,+ \
CDEF:SIM5=SIM5C,SIM5N,+ \
LINE2:SIM1#0000FF:"SIM1" \
LINE2:SIM2#00FFFF:"SIM2" \
LINE2:SIM3#00FF00:"SIM3" \
LINE2:SIM4#F00F00:"SIM4" \
LINE2:SIM5#FFFF00:"SIM5"

すると下記のように「IIJmioの1年分使用量」のうち日本語文字列である「の」「年分使用量」が化けている。

では、何を追加インストールすればいいのか?
CentOS5環境では「fonts-japanese」であった。
しかし、CentOS7環境ではこのパッケージ名は存在していない。

CentOS5環境でのパッケージ情報を確認

# yum info fonts-japanese
Loaded plugins: fastestmirror, priorities
base                                                                  3667/3667
Installed Packages
Name       : fonts-japanese
Arch       : noarch
Version    : 0.20061016
Release    : 4.el5
Size       : 40 M
Repo       : installed
Summary    : フリーな日本語のビットマップ/TrueType フォント
License    : Distributable
Description: This package provides the free Japanese Bitmap/TrueType fonts.
#

そして、CentOS7環境でTrueTypeで検索してみる。

# yum search "TrueType"
読み込んだプラグイン:fastestmirror, langpacks
Loading mirror speeds from cached hostfile
 * base: www.ftp.ne.jp
 * epel: ftp.jaist.ac.jp
 * extras: www.ftp.ne.jp
 * updates: www.ftp.ne.jp
============================ N/S matched: TrueType =============================
SDL2_ttf.x86_64 : TrueType font rendering library for SDL2
SDL_ttf.x86_64 : Simple DirectMedia Layer TrueType Font library
baekmuk-ttf-batang-fonts.noarch : Korean Baekmuk TrueType Batang typeface
baekmuk-ttf-dotum-fonts.noarch : Korean Baekmuk TrueType Dotum typeface
baekmuk-ttf-fonts-common.noarch : Common files for Korean Baekmuk TrueType fonts
baekmuk-ttf-fonts-ghostscript.noarch : Ghostscript files for Korean Baekmuk
                                     : TrueType fonts
baekmuk-ttf-gulim-fonts.noarch : Korean Baekmuk TrueType Gulim typeface
baekmuk-ttf-hline-fonts.noarch : Korean Baekmuk TrueType Headline typeface
cjkuni-ukai-fonts.noarch : Chinese Unicode TrueType font in Kai face
cjkuni-uming-fonts.noarch : Chinese Unicode TrueType font in Ming face
libfonts.noarch : TrueType Font Layouting
mftrace.x86_64 : Utility for converting TeX bitmap fonts to Type 1 or TrueType
               : fonts
sazanami-fonts-common.noarch : Common files for Sazanami Japanese TrueType fonts
sazanami-gothic-fonts.noarch : Sazanami Gothic Japanese TrueType font
sazanami-mincho-fonts.noarch : Sazanami Mincho Japanese TrueType font
ttembed.x86_64 : Remove embedding limitations from TrueType fonts
ttf2pt1.x86_64 : TrueType to Adobe Type 1 font converter
ttmkfdir.x86_64 : Utility to create fonts.scale files for truetype fonts
vlgothic-fonts.noarch : Japanese TrueType font
vlgothic-p-fonts.noarch : Proportional Japanese TrueType font

  Name and summary matches only, use "search all" for everything.
#

「vlgothic-fonts.noarch : Japanese TrueType font」が怪しそうなので「yum install vlgothic-fonts.noarch」を実行してインストール。

そして、rrdtoolsを再実行して生成した画像が↓

というわけで、CentOS7環境でmunin/rrdtoolsで日本語文字列が化けるときは「vlgothic-fonts」をインストールすればよい、ということがわかった。

2022/05/13追記:Oracle Linux8の場合、vlgothic-fontsはEPEL収録になっていたため、「oracle-epel-release-el8」をインストールしたあとに「vlgothic-fonts」をインストールすることになる。

vROpsで取得しているデータをPowerCLI経由でcsv出力する(複数の出力結果を1つにまとめる方法)



vROpsで取得しているvSphere環境に関する情報は、通常、vROpsのレポートやダッシュボードなどで確認する。
csvでほしい場合は、レポートで出力させたりする。

しかし、vROpsのGUIでは、全ての仮想マシンについて、指定期間内のCPU/メモリの使用容量を取得する、といった操作を行うことができない。
できるのは、「1台の仮想マシンについて指定期間内のCPU/メモリの使用容量を取得する」という操作を全ての仮想マシンに対して個別に実行する、ということである。

そんなのは使いにくい。

PowerCLIを使うと、vROpsで取得済みのデータをGet-OMStatを使用することで取得することができる。
(なお、予測のデータについては、PowerCLI経由では取得できない)

しかし、Get-OMStatで取得できるデータは、1つのメトリックについてのみであるため、CPUとメモリの使用量について取得しようとした場合、それぞれGet-OMStatを実行する必要がある。

CPUの使用量/使用率とメモリの使用量について取得すると以下のようになる。

$cpuusage=Get-OMStat -Resource $vmguest.Name -Key 'cpu|usage_average' -From $startdate -To $enddate -RollupType avg -IntervalType Hours -IntervalCount $interval 
$cpuusagemhz=Get-OMStat -Resource $vmguest.Name -Key 'cpu|usagemhz_average' -From $startdate -To $enddate -RollupType avg -IntervalType Hours -IntervalCount $interval
$memusage=Get-OMStat -Resource $vmguest.Name -Key 'mem|host_usage' -From $startdate -To $enddate -RollupType avg -IntervalType Hours -IntervalCount $interval 

3つの変数にそれぞれデータが入っているため、このままでは1つのCSVファイルに出力ができない。

これを、1つにまとめようとすると以下のようになる。

$cpuusage=Get-OMStat -Resource $vmguest.Name -Key 'cpu|usage_average' -From $startdate -To $enddate -RollupType avg -IntervalType Hours -IntervalCount $interval 
$cpuusagemhz=Get-OMStat -Resource $vmguest.Name -Key 'cpu|usagemhz_average' -From $startdate -To $enddate -RollupType avg -IntervalType Hours -IntervalCount $interval
$memusage=Get-OMStat -Resource $vmguest.Name -Key 'mem|host_usage' -From $startdate -To $enddate -RollupType avg -IntervalType Hours -IntervalCount $interval 

$results=$cpuusage|ForEach-Object {
        $output = New-Object -TypeName PSObject
        $output | Add-Member -MemberType NoteProperty -Name "Time" -Value $_.Time
        $output | Add-Member -MemberType NoteProperty -Name "Name" -Value $_.Resource
        $output | Add-Member -MemberType NoteProperty -Name "CpuAverage" -Value $_.Value
        $output | Add-Member -MemberType NoteProperty -Name "CpuMHzAverage" -Value `
            ($cpuusagemhz | where { $_.Time -eq $output.Time } |Select-Object -Last 1 ).Value
        $output | Add-Member -MemberType NoteProperty -Name "MemAverage" -Value `
            ($memusage | where { $_.Time -eq $output.Time } |Select-Object -Last 1 ).Value
        $output
}

$results | Export-Csv output.csv -Encoding UTF8 -NoTypeInformation

これで、1つのcsvとして、3つのメトリックの結果を取得できるようになる。

IIJmioクーポンスイッチAPIを使って使用量グラフ作成



IIJmioクーポンスイッチAPI」というものが公開された。

AndroidアプリからこのAPIを使う、というのが想定されている使われ方だと思うんですが、違う使い方をしてみた。
というのは、「データ利用量照会」という機能を見つけ、これを利用すれば1年分のデータ使用量グラフが作れる、と思ったからです。

幸い、常時起動のサーバがあるので、そいつに仕込めばいいか、と、やってみました。

まずは、完成品をご覧ください。
test

現在SIMを4枚もっているので、こんなグラフになっています。
メインで使ってるのがSIM2、SIM4はSMS対応のものでテストに使用。
SIM3はうちの奥さんに渡しているもの、SIM1は実家においてあるルータ、という感じです。

さて、このグラフ作るまでに行ったことですが、まず最初はアクセストークン取得です。
いろいろ悩んだんですが、適当な手法をとっています。

まず、redirect_uriとして適当なCGIを作りました。

#!/usr/bin/perl
print "Content-Type: text/plain; charset=UTF-8\n\n";
print "test\n";

えぇ、適当過ぎますね。

そして、普通のHTMLを作ります。

<html>
<head>
<title>iijmio</title>
</head>
<body>

<a href="https://api.iijmio.jp/mobile/d/v1/authorization/?response_type=token&client_id=<DeveloperID>&state=test&redirect_uri=http%3A%2F%2F~.osakana.net%2Ftest.cgi">go to IIJMIO</a>

</body>
</html>

redirect_uriには、先ほど作成した適当なCGIのアドレスを記載します。

ブラウザで作成したhtmlにアクセスし、IIJmioの認証を行い、正常に通ると、redirect_uriに指定したURLに対して、戻ってきます。
ブラウザのURL欄に表示された文字列から「access_token=~」という記述を見つけ、アクセストークンを取得します。
ちなみに、このアクセストークン、7776000秒有効です。つまり90日間です。
IIJmio側に30日分のデータが保管されているので120日以内に1回手動で更新すればいいか、と考え、テキトーな実装になっています。

次に、利用量取得のperlスクリプト作成。

#!/usr/bin/perl
use strict;
use warnings;
use LWP;
use URI::Escape;
use JSON;
use Time::Local;

my $lwpua = LWP::UserAgent->new;

my $url="https://api.iijmio.jp/mobile/d/v1/log/packet/";

my $developerid="<DeveloperID>";
my $usertoken  ="<アクセストークン>";

my $lwpreq = HTTP::Request->new(GET => "$url");
$lwpreq->header("X-IIJmio-Developer" => "$developerid");
$lwpreq->header("X-IIJmio-Authorization" => "$usertoken");
my $lwpres= $lwpua->request($lwpreq);
my $data = decode_json($lwpres->content);

for(my $i=0;$i<@{$data->{packetLogInfo}};$i++){
        #print $i . ":" . $data->{packetLogInfo}->[$i]->{hddServiceCode} ."\n";
        my $hddServiceCode=$data->{packetLogInfo}->[$i]->{hddServiceCode};

        for(my $j=0;$j<@{$data->{packetLogInfo}->[$i]->{hdoInfo}};$j++){
                #print $i . "-" . $j . ":" . $data->{packetLogInfo}->[$i]->{hdoInfo}->[$j]->{hdoServiceCode} . "\n";
                my $hdoServiceCode=$data->{packetLogInfo}->[$i]->{hdoInfo}->[$j]->{hdoServiceCode};
                if(! -f "$hdoServiceCode.rrd"){
                      print "rrdtool create $hdoServiceCode.rrd --start 1384786740 --step 86400 DS:withCoupon:GAUGE:86400:0:U DS:withoutCoupon:GAUGE:86400:0:U RRA:LAST:0.5:1:100000 \n";
                      system("rrdtool create $hdoServiceCode.rrd --start 1384786740 --step 86400 DS:withCoupon:GAUGE:86400:0:U DS:withoutCoupon:GAUGE:86400:0:U RRA:LAST:0.5:1:100000");

                }

                for(my $k=0;$k<@{$data->{packetLogInfo}->[$i]->{hdoInfo}->[$j]->{packetLog}};$k++){
                      #print "   " . $data->{packetLogInfo}->[$i]->{hdoInfo}->[$j]->{packetLog}->[$k]->{date} ;
                      #print ":" . $data->{packetLogInfo}->[$i]->{hdoInfo}->[$j]->{packetLog}->[$k]->{withCoupon} ;
                      #print ":" . $data->{packetLogInfo}->[$i]->{hdoInfo}->[$j]->{packetLog}->[$k]->{withoutCoupon} ;
                      #print "\n";
                      my $d=$data->{packetLogInfo}->[$i]->{hdoInfo}->[$j]->{packetLog}->[$k]->{date};
                      my $year = substr($d,0,4);
                      my $mon  = substr($d,4,2) - 1;
                      my $mday = substr($d,6,2);
                      my $unixtime = timelocal(0,59,23,$mday,$mon,$year);
                      my $withCoupon=$data->{packetLogInfo}->[$i]->{hdoInfo}->[$j]->{packetLog}->[$k]->{withCoupon};
                      my $withoutCoupon=$data->{packetLogInfo}->[$i]->{hdoInfo}->[$j]->{packetLog}->[$k]->{withoutCoupon};
                      print "rrdtool update $hdoServiceCode.rrd $unixtime:$withCoupon:$withoutCoupon \n";
                      system("rrdtool update $hdoServiceCode.rrd $unixtime:$withCoupon:$withoutCoupon");
                }
        }
}

これを「get.pl」というファイル名で保存します。
実行すると、「hdo810xxxxx.rrd」というような感じのファイルがSIMカード分作成されます。
なお、手抜きをしているので、2回目以降は、同じ値を入力しようとし、「ERROR: hdo8371xxxx.rrd: illegal attempt to update using time 1387378740 when last update time is 1387378740 (minimum one second step)」みたいなエラーがでてしまいますが、仕様です。
また、rrdtoolは一度登録した情報の更新ができない構造をしているので、日付が変わる直前に実行することを推奨します。

で・・・グラフ作成は以下の様な感じで、情報取得と連続で行わせています。
現在SIMが4枚あるので、4枚分を集計しています。
クーポン使用の有無は区別せず合算としています。

#!/bin/bash
cd /home/~/mio
./get.pl
rrdtool graph iijmio-use.png --imgformat=PNG --end now --start end-1months \
--vertical-label "MB" \
--title="IIJmioの使用量" \
DEF:SIM1C=hdo8038xxxx.rrd:withCoupon:LAST \
DEF:SIM1N=hdo8038xxxx.rrd:withoutCoupon:LAST \
DEF:SIM2C=hdo8100xxxx.rrd:withCoupon:LAST \
DEF:SIM2N=hdo8100xxxx.rrd:withoutCoupon:LAST \
DEF:SIM3C=hdo8100xxxx.rrd:withCoupon:LAST \
DEF:SIM3N=hdo8100xxxx.rrd:withoutCoupon:LAST \
DEF:SIM4C=hdo8371xxxx.rrd:withCoupon:LAST \
DEF:SIM4N=hdo8371xxxx.rrd:withoutCoupon:LAST \
CDEF:SIM1=SIM1C,SIM1N,+ \
CDEF:SIM2=SIM2C,SIM2N,+ \
CDEF:SIM3=SIM3C,SIM3N,+ \
CDEF:SIM4=SIM4C,SIM4N,+ \
LINE1:SIM1#0000FF:"SIM1" \
LINE2:SIM2#00FFFF:"SIM2" \
LINE3:SIM3#00FF00:"SIM3" \
LINE4:SIM4#F00F00:"SIM4"

で、これをサーバのcrontabに突っ込んで、23:58に実行する設定しました。
さて、これでちゃんと更新し続けてくれるといいのですが・・・


APIが公開されて速攻作成&記事公開したところ、IIJmioの人に発見された模様。


2013/12/24追記

しばらく運用してみた結果、見にくかったので、グラフ作成については、以下の様に変更した。

rrdtool graph iijmio-use.png --imgformat=PNG \
--height=300 \
--lower-limit=0 \
--end now --start end-1months \
--vertical-label "MB" \
--title="IIJmioの使用量" \
DEF:SIM1C=hdo8038xxxx.rrd:withCoupon:LAST \
DEF:SIM1N=hdo8038xxxx.rrd:withoutCoupon:LAST \
DEF:SIM2C=hdo8100xxxx.rrd:withCoupon:LAST \
DEF:SIM2N=hdo8100xxxx.rrd:withoutCoupon:LAST \
DEF:SIM3C=hdo8100xxxx.rrd:withCoupon:LAST \
DEF:SIM3N=hdo8100xxxx.rrd:withoutCoupon:LAST \
DEF:SIM4C=hdo8371xxxx.rrd:withCoupon:LAST \
DEF:SIM4N=hdo8371xxxx.rrd:withoutCoupon:LAST \
CDEF:SIM1=SIM1C,SIM1N,+ \
CDEF:SIM2=SIM2C,SIM2N,+ \
CDEF:SIM3=SIM3C,SIM3N,+ \
CDEF:SIM4=SIM4C,SIM4N,+ \
LINE2:SIM1#0000FF:"SIM1" \
LINE2:SIM2#00FFFF:"SIM2" \
LINE2:SIM3#00FF00:"SIM3" \
LINE2:SIM4#F00F00:"SIM4"

iijmio2

「LINE数字:~」の数字部分の意味を取り違えていたという・・・太さの意味だったか・・・


2014/12/19追記

作ってから約1年が経過しました。
最近はこんなグラフにしています。(横軸のめもりを日付にした)

rrdtool graph iijmio-use.png --imgformat=PNG \
--height=300 \
--lower-limit=0 \
--end now --start end-2months \
--vertical-label "MB" \
--x-grid DAY:1:WEEK:1:WEEK:1:0:%m/%d \
--title="IIJmioの使用量" \
DEF:SIM1C=hdo8038xxxx.rrd:withCoupon:LAST \
DEF:SIM1N=hdo8038xxxx.rrd:withoutCoupon:LAST \
DEF:SIM2C=hdo8100xxxx.rrd:withCoupon:LAST \
DEF:SIM2N=hdo8100xxxx.rrd:withoutCoupon:LAST \
DEF:SIM3C=hdo8100xxxx.rrd:withCoupon:LAST \
DEF:SIM3N=hdo8100xxxx.rrd:withoutCoupon:LAST \
DEF:SIM4C=hdo8371xxxx.rrd:withCoupon:LAST \
DEF:SIM4N=hdo8371xxxx.rrd:withoutCoupon:LAST \
CDEF:SIM1=SIM1C,SIM1N,+ \
CDEF:SIM2=SIM2C,SIM2N,+ \
CDEF:SIM3=SIM3C,SIM3N,+ \
CDEF:SIM4=SIM4C,SIM4N,+ \
LINE2:SIM1#0000FF:"SIM1" \
LINE2:SIM2#00FFFF:"SIM2" \
LINE2:SIM3#00FF00:"SIM3" \
LINE2:SIM4#F00F00:"SIM4"

mio-20141219

そして、1年分

rrdtool graph iijmio-use-year.png --imgformat=PNG \
--height=300 \
--width=600 \
--lower-limit=0 \
--end now --start end-14months \
--vertical-label "MB" \
--x-grid WEEK:1:MONTH:1:MONTH:1:0:%m/%d \
--title="IIJmioの1年分使用量" \
DEF:SIM1C=hdo8038xxxx.rrd:withCoupon:LAST \
DEF:SIM1N=hdo8038xxxx.rrd:withoutCoupon:LAST \
DEF:SIM2C=hdo8100xxxx.rrd:withCoupon:LAST \
DEF:SIM2N=hdo8100xxxx.rrd:withoutCoupon:LAST \
DEF:SIM3C=hdo8100xxxx.rrd:withCoupon:LAST \
DEF:SIM3N=hdo8100xxxx.rrd:withoutCoupon:LAST \
DEF:SIM4C=hdo8371xxxx.rrd:withCoupon:LAST \
DEF:SIM4N=hdo8371xxxx.rrd:withoutCoupon:LAST \
CDEF:SIM1=SIM1C,SIM1N,+ \
CDEF:SIM2=SIM2C,SIM2N,+ \
CDEF:SIM3=SIM3C,SIM3N,+ \
CDEF:SIM4=SIM4C,SIM4N,+ \
LINE2:SIM1#0000FF:"SIM1" \
LINE2:SIM2#00FFFF:"SIM2" \
LINE2:SIM3#00FF00:"SIM3" \
LINE2:SIM4#F00F00:"SIM4"

test-year-20141219

おまけ:上記のグラフの利用率変動の解説。

SIM1はミニマムスタートプラン、SIM2/3/4はファミリーシェアプランで、SIM3はmicroSIM、SIM4はnanoSIM/SMS付。

・2013/12頃
 メイン機CP-D02:SIM2
 偽iPhone5s(Thunderbird i5s):SIM4
 奥さんのP-01D:SIM3
 奥さん実家の緊急用ルータ:SIM1
・2014/01頃
 ほとんど使用されていないSIM1の容量がもったいないので入れ替え
 メイン機CP-D02:SIM2→SIM1
 奥さん実家の緊急用ルータ:SIM1→SIM2
 偽iPhone5s(Thunderbird i5s):SIM4
 奥さんのP-01D:SIM3
・2014/02頃の変更点
 Thunderbid i5sの液晶を割ったので余ったSMS付SIM4をメイン機へ 
 メイン機CP-D02:SIM1→SIM4
 奥さん実家の緊急用ルータ:SIM2
 奥さんのP-01D:SIM3
・2014/03頃の変更点
 Covia CP-F03aが来たのでがんばって使用開始。
 それに伴い余剰になったCovia CP-D02を奥さんのに充当
 メイン機CP-F03a:SIM4 & SIM1
 奥さん実家の緊急用ルータ:SIM2
 奥さんのCP-D02:SIM3
・2014/06頃の変更点
 JIAYU F1購入。使い勝手が良かったので、メイン機に変更。
 メイン機JIAYU F1:SIM4
 予備機CP-F03a:SIM1
 奥さん実家の緊急用ルータ:SIM2
 奥さんのCP-D02:SIM3

・2014/11頃の変更点
 GMOBBのWiMAXを使い始めたのでメイン機SIM4の使用量低下

・2014/12頃の変更点
 自宅のフレッツが微妙に不安定なことが多いので、奥さんCP-D02のWiFiをオフにしてみた。

munin向けのpcsensorプラグインを作った



上海問屋のDNSB-35137など、いくつかの販路で取り扱われているUSB接続の温度計 RDing TEMPerV1.2。

その温度をmuninで計測するためにpluginを作った。

今回考慮が必要だった点
・USB温度計を2つつなぐ
・つなぐUSB BUSが同じであるため、CentOS5上で見分けがつかない
 (TEMPerV1.2ではシリアルを含めデバイス内のパラメータが全部一緒で見分ける方法がない)
・2つの温度計の設置位置は違うので、温度差が5度ぐらいある
・pcsensorコマンド実行時、デバイスがオフラインになることが良くある
 (参考→USB温度計 TEMPerV1.2は計測ミスが多い)

あまり複雑なことをするのも嫌だったので、単純な実装としました。

・温度が2つ取得できるまで、再試行する
・温度が低い方から順にソートして「usbtemper0」「usbtemper1」としていく

また、内部で使うコマンドは、うちで作成した「pcsensor-1.0.2 for TEMPerV1.2 with multi device support」を使います。

USB温度計を1個しか繋がない人は「my $maxdevice=1;」に書き換えてください。

#!/usr/bin/perl -w

my $options="-d";
my $maxdevice=2;

my $arg=$ARGV[0];
if(!$arg){ $arg=""; }

if("$arg" eq "config"){
    print "graph_title USB Temperature Sensor\n";
    print "graph_vtitle Celsius\n";
    print "graph_category sensors\n";
    print "graph_args --base 1000 -l 0\n";
}

my @devlist;
my $count=0;
while($count<$maxdevice){
    open(FILE,"/usr/local/bin/pcsensor $options|");
    while(my $line=<FILE>){
        $line =~ s/\n//ig;

        if($line =~ /Temperature/){
            my @strs=split(/ /,$line);

            my $devnumber=$strs[3] ."-". $strs[5];
            my $value=$strs[8];
            $value=~ s/C//ig;
            #$value=int($value);

            $devlist[$count]=$value;
            $count++;
        }
    }
    close(FILE);
}

my $counttmp=0;
foreach $value (sort @devlist){
    if("$arg" eq "config"){
        print "usbtemper".$counttmp.".label USB temper".$counttmp."\n";
    }else{
        print "usbtemper".$counttmp.".value ".$value."\n";
    }
    $counttmp++;
}

これ、仕掛けて3時間ぐらいしたら、kernel panic起こしやがった・・・