ズンドコキヨシをPerlとZabbixで実現した、という話

# この記事は？
- [ズンドコキヨシ](http://qiita.com/shunsugai@github/items/971a15461de29563bf90)というプログラミング例題があるそうだ。なるほどFizzBuzzのようなものか。
- せっかくなので自分でもやってみよう。Perlで。
- ついでなのでZabbixでもズンドコさせてみようか。

# まずは環境情報
## 環境情報
| 項目 | 情報 |
|:-:|:-:|
|CentOS|CentOS Linux release 7.2.1511|
|Zabbix|3.0.2rc1 rev59391|
|Perl|v5.16.3|

# ズンドコキヨシを作る
## zdkiyoshi.pl
コードをどーん。

```pl
#!/usr/bin/perl
#------------------------------------
# Author        : Hiroki.lzh
# Descripsion   : ZundokoKiyoshi
#------------------------------------

#---------------------------
#  [Module] Using Modules
#---------------------------
use strict;
use warnings;
use Getopt::Long;
use Time::Local;
use Test::More;

#---------------------------
#  [Config] System Config
#---------------------------
my $version     ="1";
my $revision    ="0";
my $revdate     ="2016/07/10";
my $sysname     ="ZunDoko Kiyoshi";

#---------------------------
#  [Config] Script Config
#---------------------------
my ($zun, $doko)= ("ずん", "どこ");
my $Kiyoshi     = "＼きよし／\n";

#---------------------------
#  [Func] SetOption
#       Return
#               $opts{mode} = 0: Zabbix Zundoko
#               $opts{mode} = 1: Normal Zundoko
#               exit 0: Normal Exit
#               exit 1: Error Exit
#       Exit
#               0 = Normal Exit
#---------------------------
sub SetOption() {
        my %opts = ();
        GetOptions(\%opts, 'version', 'help', 'mode=i');

        if( defined $opts{version} == 1) {
                printf("%s ver.%s.%s (created %s)\n", $sysname, $version, $revision, $revdate);
                exit 0;
        } elsif ( defined $opts{help} == 1) {
                print   "Usage: $0 [-hv] -m <num> \n\n".
                        "Options:\n".
                        "  -h --help \t Give this help.\n".
                        "  -v --version \t Display version number.\n".
                        "  -m num or --mode num \t Set Mode.\n".
                        "                       \t   0 : ZunDoko only once output.\n".
                        "                       \t   1 : Repeat ZunDoko until \"Kiyoshi pattern\"  comes out.\n";
                exit 0;
        } elsif ( defined $opts{mode} == 1) {
                return $opts{mode};
        } else {
                print "Please set option --mode <num>. \n";
                exit 1;
        }
}

#---------------------------
#  [Func] GetZunDoko
#       Input
#               Nothing
#       Return
#               str = @Zundoko[0] or @Zundoko[1]
#---------------------------
sub GetZunDoko {
        my @ZunDoko = ($zun, $doko);
        my $num = int(rand(2));
        return $ZunDoko[$num];
}

#---------------------------
#  [Func] ZunDokoOnce
#       Input
#               Nothing
#       Return
#               0 = Success
#---------------------------
sub ZunDokoOnce {
        print &GetZunDoko();
        return 0;
}

#---------------------------
#  [Func] ZunDokoRepeat
#       Input
#               Nothing
#       Return
#               0 = Success
#---------------------------
sub ZunDokoRepeat {
        my $result = 0;
        my $count = 0;
        my @check_array   = ("","","","","");
        my @kiyoshi_array = ("0","0","0","0","1");

        while ( $result == "0" ){
                my $num = int(rand(2));
                if ( $num == 0 ){
                        print $zun;
                } else {
                        print $doko;
                }

                shift(@check_array);
                push(@check_array,$num);
                $result = eq_array(\@check_array,\@kiyoshi_array);
        }

        print $Kiyoshi;
        return 0;
}

#---------------------------
#  [Main] Main Programs
#---------------------------

# OptionCheck
my $mode = &SetOption();

if ( $mode == 0 ){
        &ZunDokoOnce();
        exit 0;
} elsif ( $mode == 1 ) {
        &ZunDokoRepeat();
        exit 0;
} else {
        print "Mode: $mode is unknown mode.\n";
        exit 1;
}

```

## 簡単にお話
- のちのZabbixでズンドコさせるためにmode 0を用意、「ずん」もしくは「どこ」を一回出力して終わり。
- 改行を入れていないのはZabbix側で拾うときに影響を与えないように、という配慮。
- mode 1では通常のズンドコキヨシを実行。
- int(rand(2))で0≦$num＜2の小数点を含む乱数生成から整数を取り出し、0だったら「ずん」1だったら「どこ」とした。
- rand関数の範囲から考えると厳密には「どこ」よりも「ずん」のほうが発生しやすい。
- ズンドコキヨシの肝である「ズンドコできたかどうか」のチェック、すなわち配列比較をTest::Moreモジュールのeq_array関数を使用。
- さくっと作るためにTestモジュール使ったけど、でもTestモジュール使うのはちょっとなぁ…とも思っている。

## 実行結果例
```bash
# ./zdkiyoshi.pl --mode 0
ずん[root@StarPlatinum]#
[root@StarPlatinum]#  
[root@StarPlatinum]# ./zdkiyoshi.pl --mode 1
どこ[root@StarPlatinum]#
[root@StarPlatinum]# ./zdkiyoshi.pl --mode 1
ずんどこずんどこずんずんずんどこずんずんずんどこずんどこずんどこどこずんどこずんずんどこずんどこずんどこどこずんどこどこずんどこどこどこどこずんずんどこどこずんずんどこずんどこずんどこどこどこどこどこどこどこどこずんどこずんずんどこずんずんどこどこどこどこどこずんどこどこどこどこずんどこどこどこずんずんどこどこどこどこどこどこずんどこずんずんどこずんずんどこずんずんずんどこどこずんどこずんどこずんどこずんどこどこずんずんどこずんどこずんどこどこどこどこずんずんどこどこどこずんずんずんどこどこずんずんずんどこずんどこずんどこずんどこどこずんどこずんどこずんずんどこずんずんずんどこどこずんどこずんどこずんずんどこずんずんずんどこどこどこずんどこどこずんどこずんどこどこどこどこどこずんどこどこずんどこずんどこずんどこどこずんずんどこずんどこどこずんずんずんずんどこ＼きよし／
[root@StarPlatinum]#
[root@StarPlatinum]# ./zdkiyoshi.pl --mode 1
どこどこずんどこずんどこずんどこずんずんずんどこずんずんどこずんずんずんずんずんどこ＼きよし／
```

# Zabbixでズンドコする
## 監視設定として導入する
みんな大好きsystem.runでエージェント経由でスクリプトを発行する。
![WS000016.JPG](https://qiita-image-store.s3.amazonaws.com/0/129674/af63fa8e-e8eb-8d4c-37f0-72c654024306.jpeg)

```
アイテムキー：system.run["/etc/zabbix/externalscripts/zdkiyoshi.pl -m 0",wait]
```

## トリガー設定を仕込む
何を以てズンドコ完了とするか？がポイントだが、ここでは
- 最新の5回分の監視結果において、「ずん」が4回監視結果として取得されている
  ⇒過去5回のうち、4回「ずん」が存在する(count)
- 最新の取得データは「どこ」である
  ⇒最新の取得データで「どこ」が存在する(regexp,iregexp,str)
の2条件をAND条件でつないだ。
![WS000017.JPG](https://qiita-image-store.s3.amazonaws.com/0/129674/2d08a0f5-6fbb-7de7-aebe-a45928c74d8a.jpeg)

Zabbix3.xからAND条件のつなぎが「&」ではなく「and」になったこと、
ノットイコールにあたるものが「#」ではなく「<>」に変更になっている点は注意だ。

```
{StarPlatinum:system.run["/etc/zabbix/externalscripts/zdkiyoshi.pl -m 0",wait].count(#5,"ずん","like")}=4 and {StarPlatinum:system.run["/etc/zabbix/externalscripts/zdkiyoshi.pl -m 0",wait].iregexp(どこ)}<>0
```

## ＼ キ・ヨ・シ ／
ずん・ずんずん・ずんどこ
![WS000014.JPG](https://qiita-image-store.s3.amazonaws.com/0/129674/c54bf0c8-4938-7064-5c03-0043c44aaf50.jpeg)

＼ キ・ヨ・シ ／
![WS000015.JPG](https://qiita-image-store.s3.amazonaws.com/0/129674/6035f7c1-2ad7-fee4-f632-c3cb81065d35.jpeg)


* * *
以上