2011年5月20日金曜日

Zabbix 1.6と1.8の時刻設定の注意点

Zabbixには何ヶ所か時刻を設定する項目があります。

たとえば通知に利用するメールアドレスの設定であるメディアや、監視データを受信する設定の例外の更新間隔などがそれです。それぞれのヶ所には以下のように曜日と時刻を設定する決まりになっています。

0-7,00:00-23:59

最初の0-7が月曜から日曜、後ろが時間と分を指します。デフォルトは上記のように0-7,00:00-23:59になっているので、Zabbixを触ったことがある方は見かけたことがあると思います。

実は1.6と1.8にはこの設定に落とし穴があって、上記のデフォルトでは23:59-24:00の間の1分間が無効の状態になってしまいます。この問題で一番影響があるのは通知に利用するメールアドレスの設定で、デフォルトの設定では23:59-24:00の間の1分間に発生した障害についてはメールが送信されない状態になってしまいます。

この問題を回避するためには、0-7,00:00-24:00と設定しておけばすべての曜日と時間で有効になります。

ZABBIX-JP版ではの1.8.3以降、本家Zabbix SIA版では次のマイナーバージョンアップである1.8.6から上記のデフォルト値が0-7,00:00-24:00になるように修正が行われています。

バージョンアップでデフォルト値が変わったとしても、すでにいちどメディアを設定している場合は00:00-23:59の値がデータベースに保存されているので、特に気にしていなかった人は設定を見直しておいた方が良いでしょう。

ところで、この問題は1.6移行で発生し、1.4以前では発生しません。問題となるソースは、1.4.7では以下のようになっています。

src/libs/zbxcommon/misc.c 753行目あたり check_time_peroid関数内

int     check_time_period(char *period, time_t now)
{
...

        if(now == (time_t)NULL) now = time(NULL);
        
        tm = localtime(&now);

        day=tm->tm_wday;
        if(0 == day)    day=7;
        hour = tm->tm_hour;
        min = tm->tm_min;

ここで現在の時間を取得して、曜日、時間、分をそれぞれ変数に代入してます。

...

        if(sscanf(s,"%d-%d,%d:%d-%d:%d",&d1,&d2,&h1,&m1,&h2,&m2) == 6)
        {
                zabbix_log( LOG_LEVEL_DEBUG, "%d-%d,%d:%d-%d:%d",d1,d2,h1,m1,h2,m2);
                if( (day>=d1) && (day<=d2) && (60*hour+min>=60*h1+m1) && (60*hour+min<=60*h2+m2))

そしてここでWebインターフェースから入力された時刻と比較しているわけです。分単位なので23:59:30でも23:59と計算されます。

これが1.6移行では、同じsrc/libs/zbxcommon/misc.c 282行目あたり check_time_period関数内

int     check_time_period(const char *period, time_t now)
{

...

        if (now == (time_t)NULL)
                now = time(NULL);

        tm = localtime(&now);
        day = 0 == tm->tm_wday ? 7 : tm->tm_wday;
        sec = 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;

ここで1.4とは違い秒まで変数に入れたうえで、

        {
                zabbix_log(LOG_LEVEL_DEBUG, "%d-%d,%d:%d-%d:%d", d1, d2, h1, m1, h2, m2);

                if (day >= d1 && day <= d2 && sec >= 3600 * h1 + 60 * m1 && sec <= 3600 * h2 + 60 * m2)
                {
                        ret = 1;
                        break;
                }
        }

秒単位で計算しています。結果として、現在時刻が23:59:30>23:59:00となってしまい時間外と判定されてしまうというわけです。

0 件のコメント: