[CentOS]muninでhttp_loadtimeの値が取れない場合の対処


おはようございます。早朝muninおじさんです。munin監視対象でhttp_loadtimeの値が取れず、 /usr/share/munin/plugins/http_loadtime を修正したので対処メモを残します。監視対象の環境は以下の通りです。

$ cat /etc/redhat-release 
CentOS release 6.6 (Final)
$ yum list installed munin-node | egrep munin-node | awk '{print $1,$2,$3}'
munin-node.noarch 2.0.25-2.el6 @epel
$ yum list installed httpd | egrep httpd | awk '{print $1,$2,$3}'
httpd.x86_64 2.2.15-39.el6.centos @base

監視対象がWEBサーバーだったので、いつものようにmunin-nodeをインストールしてhttp_loadtimeを監視項目に加えたのですが・・・

$ sudo ln -s /usr/share/munin/plugins/http_loadtime /etc/munin/plugins/http_loadtime

munin-runで値が取れているか確認したところ

$ sudo munin-run http_loadtime
which: no time in (/usr/sbin:/usr/bin:/sbin:/bin)
/etc/munin/plugins/http_loadtime: line 78: syntax error: unexpected end of file

いきなり2つエラーが出てしまいました。。。

■ timeコマンドがない?

まず1つ目

time_bin=`which time`

なんて変数指定があるのですが、bash内部コマンドのtimeだとwhichでPATHが表示されず、異常終了します。

$ which time > /dev/null 2>&1 ; echo $?
1

なので、GNU timeをインストールしてあげる必要があります。baseリポジトリにあるのでサックリインストールしてあげましょう。

$ sudo yum install time

さて、もう一度whichでtimeコマンドのPATHを確認してみましょう。

$ which time ; echo $?
/usr/bin/time
0

timeコマンドのPATHが表示され、正常終了しました。なお、シェルがbashの場合、timeコマンドをフルパスで指定しない限り、bash内部コマンドのtimeが優先されて実行されます。だからプラグインの中でtimeコマンドを変数に格納するときに time_bin=`which time` なんてやってたんですね。

■ line 78: syntax error: unexpected end of file

http_loadtime "line 78: syntax error: unexpected end of file" でググったら、Bugzillaのページがhitして、コメント3がそのものズバリの答えでした。

d. johnson 2015-04-10 16:37:36 EDT
Line 45 of /usr/share/munin/plugins/http_loadtime has an 'if' statement that has no ending 'fi'

This is what causes it to fail.

45行目の「if ! $wget_bin -q -O /dev/null $target; then」がfiで閉じられておらず。。。というわけで、55行目の「exit 0」と56行目の「fi」の間にfiを追記。

■ timeコマンドに渡すオプションを修正する

さあ気を取り直して再実行!

$ sudo munin-run http_loadtime
/home/nullpopopo
loadtime.value /usr/bin/time: unrecognized option '--quiet'
Usage: /usr/bin/time [-apvV] [-f format] [-o file] [--append] [--verbose]
       [--portability] [--format=format] [--output=file] [--version]
       [--help] command [arg...]

あれ?カレントディレクトリが表示されてるぞ?こんな値くれとは言ってないぞ・・・。

$ cd /
$ sudo munin-run http_loadtime
/
loadtime.value /usr/bin/time: unrecognized option '--quiet'
Usage: /usr/bin/time [-apvV] [-f format] [-o file] [--append] [--verbose]
       [--portability] [--format=format] [--output=file] [--version]
       [--help] command [arg...]

あのさあ・・・。

なんでカレントディレクトリが表示されているのかはちょっと置いといて、まずは明らかにエラーの原因がわかっている「--quiet」のほうからやっつけます。GNU timeにはそんなオプション無いぞと言われたのでふたたび /usr/share/munin/plugins/http_loadtime を編集します。

$ cat /usr/share/munin/plugins/http_loadtime | grep quiet
loadtime=`$time_bin --quiet -f "%e" wget $wget_opt $target 2>&1`
$ sudo sed -i "s/--quiet //" /usr/share/munin/plugins/http_loadtime
$ cat /usr/share/munin/plugins/http_loadtime | grep quiet
$ cat /usr/share/munin/plugins/http_loadtime | egrep "time_bin -f"
loadtime=`$time_bin -f "%e" wget $wget_opt $target 2>&1`

さあもう一度実行だ!

$ sudo munin-run http_loadtime
/home/nullpopopo
loadtime.value 0.08

( ・᷄ὢ・᷅ )えー・・・試しに手動で実行してみます。

$ target=${target:-"http://localhost/"
$ wget_opt="--user-agent munin/http_loadtime --no-cache -q --delete-after"
$ time_bin=`which time`
$ $time_bin -f "%e" wget $wget_opt $target
0.05

お、値がとれた。loadtimeも変数に入れてみましょう。

$ loadtime=`$time_bin -f "%e" wget $wget_opt $target 2>&1`
$ echo $loadtime
0.02

こちらも値が取れている。どうやらtimeコマンドまわりは解決、カレントディレクトリが表示される原因は他の箇所にありそうです。

■ 結局最後は・・・

もう一度 munin-run で確認してみます。

$ sudo munin-run http_loadtime
/home/nullpopopo
loadtime.value 0.01

munin-runで値は取れるようになったものの、まだカレントディレクトリが表示されちゃってます。どうしてこうなった!?と憤怒しながらも、最後の最後を見てみると、「cd -」してるんですね。カレントディレクトリに戻るのはいいけど出力して意味あるの?ないでしょ?ということで /dev/null送りに。どうせ最後は「echo "loadtime.value $loadtime」するだけだから行ごと削除でもいいんですけど!(プンスコ)

$ sudo munin-run http_loadtime
loadtime.value 0.01

はいめでたしめでたし。やっと欲しい値が取れて、余計な出力もされなくなりました。グラフも見てみましょう。値が取れてますね。

munin-http_loadtime

最後にソース全文をぺったんこ。

#!/bin/bash
# -*- sh -*-

: << =cut

=head1 NAME

http_loadtime - Plugin to graph HTTP response time of a specific page

=head1 CONFIGURATION

The following environment variables are used by this plugin

 target - URL to fetch (default: "http://localhost/")

=head1 AUTHOR

Unknown authors
(2013) Axel Huebl

=head1 LICENSE

GPLv2

=head1 MAGIC MARKERS

 #%# family=auto
 #%# capabilities=autoconf

=cut

target=${target:-"http://localhost/"}
wget_opt="--user-agent munin/http_loadtime --no-cache -q --delete-after"
time_bin=`which time`

if [ "$1" = "autoconf" ]; then
    result="yes"
    command -v $time_bin 2>&1 >/dev/null || result=1
    command -v tr        2>&1 >/dev/null || result=1
    command -v wget      2>&1 >/dev/null || result=1
    if [ "$result" != "yes" ]; then
	echo "no (programs time, wget and tr required)"
	    exit 0
    fi
    if ! $wget_bin -q -O /dev/null $target; then

    # check if url responds
    #
    wget --spider $target $wget_opt
    if [ "$?" != "0" ]; then
        echo "no (Cannot run wget against \"$target\")"
        exit 0
    fi
    echo yes
    exit 0
    fi
fi

if [ "$1" = "config" ]; then
    echo "graph_title HTTP loadtime of a page"
    echo "graph_args --base 1000 -l 0"
    echo "graph_vlabel Load time in seconds"
    echo "graph_category network"
    echo "graph_info This graph shows load time in seconds of $target"
    echo "loadtime.label loadtime"
    echo "loadtime.info Load time"
    exit 0
fi

TEMPO_DIR=$(mktemp -dt munin_http_loadtime.XXXXXX) || exit 1

trap "rm -rf $TEMPO_DIR" EXIT

cd $TEMPO_DIR || exit 1
loadtime=`$time_bin -f "%e" wget $wget_opt $target 2>&1`
cd - > /dev/null

echo "loadtime.value $loadtime"

めでたしめでたし。 (ノ)・ω・(ヾ)ムニムニ