Zabbix Low Level Discovery でディレクトリ毎のサイズを取得する

# Zabbix Low Level Discovery でディレクトリ毎のサイズを取得する


もともと、ディスク単位はzabbixで取れていたのだが、
どこが増えているのかわかりにくかったので、ディレクトリ毎でサイズが取得できると良いと考えていた。

いろいろな記事を参考にしてようやく、作ることができた。
次回作るなら自分としては以下のような感じで作ると速くつくれるかなとおもった。

* 少しずつ更新して確認していくのがよい。
* まずはzabbix agent側では、echo で、データだけを返すようにしてみる。
* デバッグオプションを有効にしたりして、どんなキーで呼びだされているかを確認する
* なにか変更したら、テンプレートをunlink した上でデータを消してから、linkしたほうが良い。

などがよさそう。

## 自分の考えたLow Level Discoveryのおおまかな流れ

正しいものかどうかわからないが、２段階(Discovery rule, Item prototype)で値を取得しているようだ。
それぞれで別のキーの名前をつけたほうが良い感じがした。
同じキーの名前でもできるかもしれないが、デバッグするときなどは、名前をわけておいたほうがやりやすかった。

おおきくは２つのことだけ設定すれば良いようだ。

1. 自動で発見したいアイテムを探す。(Discovery rule)
2. 探したアイテムについて、値を探す。(Item Prototype)

1が成功すると、Configuration -> Hosts の中の該当するホストのところで、アイテムが追加されていることがわかる。

2が成功すると、グラフを作成することができるようになった。
別のキーの値を選んだことがよかった。

Discovery ruleのときに、jsonの中に各アイテムの値を返してみたのだが、それをzabbixサーバーに記録していく方法がよくわからなかった。
また、Item prototypeのキーの値を変えた結果、それが取得できていないことがエラーメッセージよりわかった。

エラーメッセージの例

```
10562:20151020:142302.632 item [yourhost.yourdomain:vfs.du.sz[/home/hoge]] became not supported: Received value [] is not suitable for value type [Numeric (unsigned)] and data type [Decimal]
```

## zabbix agent側のパラメータの設定

まずは

```
UserParameter=vfs.du.discovery,/etc/zabbix/scripts/vfs.du.discovery.sh /home
UserParameter=vfs.du.sz[*],sudo du -b -s $1 | awk '{print $$1}'
```

この設定だと ***/home*** だけが監視対象になるが、
もし複数のディレクトリの下を監視したいなら、***/home /data /data2*** のように追加していけば良い


### 確認

zabbix serverから***zabbix_get***を使って取得を試みた。

```
zabbix_get -s host -k "vfs.du.discovery"
```

#### 成功した場合

成功の例だと、正しく json が取得できる

```successs.json
{"data":[{"{#DIR_NAME}":"/home/hoge"}]}
```

#### 失敗した場合 

スクリプト部分の失敗の例だと、
```
ZBX_NOTSUPPORTED
```
だと表示される


## デバッグ方法

### サーバー側
基本的には、zabbix_getがうまくいけばよいはずだが、うまくいかないときは
```
/var/log/zabbix/zabbix_server.log
```
の内容を確認する

### zabbix agent側

大量にログがでるが、次の方法を実行するのが結局効率がよかった
```/etc/zabbix/zabbix_agentd.conf
LogFile=/var/log/zabbix/zabbix_agentd.log
DebugLevel=4
```

設定を変更したら、zabbix agentの再起動をしたほうが良さそう。

## 遭遇したトラブル

いくつかトラブルにあったので、メモがてら列挙しておく。

### duを実行した時に一部のディレクトリの中で Permission deny

この問題は、duのコマンドを sudo で使えるようにすれば良い
visudo などで、以下を追加する。
```
zabbix  ALL=(ALL) NOPASSWD:/bin/du
```


### du 実行時に、エラーメッセージがでる

手元で動いているのに、zabbix_getやzabbix serverごしだと正しい値が帰ってこないなどの時は、

デバッグオプションまで有効にした状態だと以下のようなログがクライアント側のログにでている。
```
sudo: sorry, you must have a tty to run sudo
```
がでるのではないかとおもうが、これは
visudo などで
```
Defaults:zabbix !requiretty
```
を、追加しておく。

## ファイル

今回作ったテンプレートと、使用したスクリプトなど

### template

```template_directory_size.xml
<?xml version="1.0" encoding="UTF-8"?>
<zabbix_export>
    <version>2.0</version>
    <date>2015-10-20T06:46:17Z</date>
    <groups>
        <group>
            <name>Linux servers</name>
        </group>
    </groups>
    <templates>
        <template>
            <template>Template Directory Size</template>
            <name>Template Directory Size</name>
            <groups>
                <group>
                    <name>Linux servers</name>
                </group>
            </groups>
            <applications/>
            <items/>
            <discovery_rules>
                <discovery_rule>
                    <name>Directory Discovery</name>
                    <type>0</type>
                    <snmp_community/>
                    <snmp_oid/>
                    <key>vfs.du.discovery</key>
                    <delay>600</delay>
                    <status>0</status>
                    <allowed_hosts/>
                    <snmpv3_contextname/>
                    <snmpv3_securityname/>
                    <snmpv3_securitylevel>0</snmpv3_securitylevel>
                    <snmpv3_authprotocol>0</snmpv3_authprotocol>
                    <snmpv3_authpassphrase/>
                    <snmpv3_privprotocol>0</snmpv3_privprotocol>
                    <snmpv3_privpassphrase/>
                    <delay_flex/>
                    <params/>
                    <ipmi_sensor/>
                    <authtype>0</authtype>
                    <username/>
                    <password/>
                    <publickey/>
                    <privatekey/>
                    <port/>
                    <filter>:</filter>
                    <lifetime>30</lifetime>
                    <description/>
                    <item_prototypes>
                        <item_prototype>
                            <name>Directory size for $1</name>
                            <type>0</type>
                            <snmp_community/>
                            <multiplier>0</multiplier>
                            <snmp_oid/>
                            <key>vfs.du.sz[{#DIR_NAME}]</key>
                            <delay>600</delay>
                            <history>90</history>
                            <trends>365</trends>
                            <status>0</status>
                            <value_type>3</value_type>
                            <allowed_hosts/>
                            <units>byte</units>
                            <delta>0</delta>
                            <snmpv3_contextname/>
                            <snmpv3_securityname/>
                            <snmpv3_securitylevel>0</snmpv3_securitylevel>
                            <snmpv3_authprotocol>0</snmpv3_authprotocol>
                            <snmpv3_authpassphrase/>
                            <snmpv3_privprotocol>0</snmpv3_privprotocol>
                            <snmpv3_privpassphrase/>
                            <formula>1</formula>
                            <delay_flex/>
                            <params/>
                            <ipmi_sensor/>
                            <data_type>0</data_type>
                            <authtype>0</authtype>
                            <username/>
                            <password/>
                            <publickey/>
                            <privatekey/>
                            <port/>
                            <description/>
                            <inventory_link>0</inventory_link>
                            <applications/>
                            <valuemap/>
                        </item_prototype>
                    </item_prototypes>
                    <trigger_prototypes/>
                    <graph_prototypes/>
                    <host_prototypes/>
                </discovery_rule>
            </discovery_rules>
            <macros/>
            <templates/>
            <screens/>
        </template>
    </templates>
</zabbix_export>
```

### ディレクトリサイズ取得用スクリプト
追記 2015-10-21
IFSに空白を追加

```bash:/etc/zabbix/scripts/vfs.du.discovery.sh
#!/bin/bash

LIST=""
for DIR in $*
do
  CLIST=`find ${DIR} -maxdepth 1 -mindepth 1 -type d`
  LIST="$LIST $CLIST"
done

if [ "${LIST}" = "" ] ;then
    echo "ZBX_NOTSUPPORTED"
    exit 1
fi

IFS=$' \n'

echo -n "{\"data\":["
FIRST=1
for DIRECTORY in ${LIST}
do
  DIRECTORY=`echo ${DIRECTORY} | tr -d ' '`
  if [ ${FIRST} -eq 1 ] ; then
      FIRST=0
  else
      echo -n ","
  fi
      echo -e -n "{\"{#DIR_NAME}\":\"${DIRECTORY}\"}"
done

echo "]}"
```

## サーバー側の設定

du に時間がかかって値がとれないことがある。
Zabbix Server がアイテムを取得するときのタイムアウトの値がデフォルトが３秒なようなので、これを長くすると解決することがある。

```
Timeout=15
```

### zabbix agent側の設定も必要だった

サーバーサイドで設定をしたらうまくいったとおもっていたが、
失敗することがあり、何度か time zabbix_get をして、時間をはかったら
３秒とでていたので、zabbix agent 側にも設定があるのかなと思い調べたところ
設定があったので、サーバーと、同様に、以下を追加した。
```
Timeout=15
```

# 追記2019-04-12

- 以下の２つの設定を間違えるとデータがなぜか届いてないとおもってしまう。
    - `zabbix agent` サーバーから、監視対象のホストのスクリプト等を実行する
    - `zabbix trapper` 監視対象のホストから、サーバーへデータを送るケースでの設定（cronでデータを送りつけるイメージ）


# 参考にしたサイト
* [mysqlのデータベースサイズを監視する - ksaitoの日記](http://d.hatena.ne.jp/ksaito11/20110518/1305816007)
* [Zabbix ローレベルディスカバリ（LLD）の拡張④ ディスク使用量の多いフォルダの監視 - Qiita](http://qiita.com/usiusi360/items/8d44fd6b975b2db40ded)
* [Capistranoでsudo実行時にttyエラー - Qiita](http://qiita.com/e2_adachi/items/7abf974d81067bd2b746)