地味に役立つ "zabbix_js"

投稿するのは2年振りくらいでしょうか。
久しぶりにZabbixの投稿をしたいと思います。

# 前置き

さて、タイトルにもあります zabbix_js、みなさんご存知でしょうか？
Zabbixのメイン機能とは外れたツールとなっているので、一度も使用せずに貴方のZabbixer人生を終えることもあるでしょう。

この内容が面白いかどうかは、Zabbixのとある機能を使用されるかどうかにかかっています。
それは、　**スクリプト (JavaScript)** です。

古くはZabbix4.2から登場したこのJavaScriptを用いた機能、４．２では「保存前処理」というアイテムの取得元から情報を取得した後、保存前処理でデータ加工しDBへ保存する際の選択処理の１つとして利用されます。

さてこのJavaScript、Zabbix4.4でも別な処理の１つとして使用する事が可能になりました。
それは**「メディアタイプ」**です。 まぁ、いわゆる障害時に送る「メール」のSMTPサーバ設定をするものであったり、外部アプリケーションと連携する為の**「メディアスクリプト」**を指定する箇所ですね。
このメディアスクリプトに追加されたWebhook機能によりJavaScriptを活用します。

ちなみに、先日登場したZabbix５．２ではアイテムのタイプとしてスクリプト(JavaScript)が登場しています。

「保存前処理」の場合は動作確認を行えるテスト機能があるので使いこなせるかもしれませんが、「メディアスクリプト」の場合はテスト機能はありますが(Zabbix5.0で追加されました)パラメータの渡しが非常に大変な場合もあるでしょう。

そこで、ここで紹介する「zabbix_js」が役に立つ事でしょう。

# zabbix_jsとは?

zabbix_jsとは、コマンドラインでZabbixで使用するJavaScriptの動作試験を行うことができるツールとなっています。
ZabbixのJavaScriptエンジンはDuktapeを使用しており、普段使われているエンジンとは若干異なる機能実装になっている事でしょう。この点も直接コマンドラインから確認できたら良いですよね。

# インストール方法
Zabbix4.4以上でrepo.zabbix.comのリポジトリからインストールされている場合は以下のコマンドで導入できます。

```
$ sudo apt install zabbix-js
```

or

```
$ sudo dnf install zabbix-js
```

直接このリポジトリからzabbix-jsのパッケージをダウンロードしてインストールする事も可能です。

# 使用方法
ここで転ぶ事が多いのでは無いでしょうか。
ヘルプを見てみましょう。

```
pi@multi-pi:~ $ zabbix_js -h
usage:
  zabbix_js -s script-file -p input-param [-l log-level] [-t timeout]
  zabbix_js -s script-file -i input-file [-l log-level] [-t timeout]
  zabbix_js -h
  zabbix_js -V

Execute script using Zabbix embedded scripting engine.

General options:
  -s,--script script-file      Specify the filename of script to execute. Specify - for
                               standard input.
  -i,--input input-file        Specify input parameter file name. Specify - for
                               standard input.
  -p,--param input-param       Specify input parameter
  -l,--loglevel log-level      Specify log level
  -t,--timeout timeout         Specify timeout in seconds
  -h --help                    Display this help message
  -V --version                 Display version number

Example:
  zabbix_js -s script-file.js -p example

Report bugs to: <https://support.zabbix.com>
Zabbix home page: <http://www.zabbix.com>
Documentation: <https://www.zabbix.com/documentation>
```

もう、言ってしまいます。
**わかりません！**

[ドキュメントページ](https://www.zabbix.com/documentation/current/manual/concepts/js) もわからない。

わかりやすいのはサンプルコードかと思いますので、ちょっとここで例を出してみますね。

``` zabbix_test.js
try {
    var req = new CurlHttpRequest(),
    params = JSON.parse(value),
    fields = {},
    res = {},
    token;

    req.AddHeader('Content-Type: application/json-rpc');

    // user.login
    fields.method = 'user.login';
    fields.id = 1;
    fields.params = {"user": params.user, "password": params.password};
    fields.jsonrpc = '2.0';
    res = JSON.parse(req.Get('http://127.0.0.1/zabbix/api_jsonrpc.php', JSON.stringify(fields)));

    token = res.result

    // user.logout
    fields = {}
    fields.method = 'user.logout';
    fields.auth = token;
    fields.id = 1;
    fields.params = {};
    fields.jsonrpc = '2.0';
    res = JSON.parse(req.Get('http://127.0.0.1/zabbix/api_jsonrpc.php', JSON.stringify(fields)));

    return JSON.stringify(res);

} catch (error) {
    Zabbix.Log(3, 'Zabbix webhook failed json : '+JSON.stringify({"fields": fields}));
    Zabbix.Log(3, 'Zabbix webhook failed : '+error);

    result = {};
}
```

単純なZabbixAPIを使用して、ユーザ名・パスワードからログイン・ログアウトをするだけの処理です。
※ user.login / user.logoutのAPI詳細はドキュメントを参照ください。
https://www.zabbix.com/documentation/current/manual/api/reference/user/login
https://www.zabbix.com/documentation/current/manual/api/reference/user/logout

ZabbixのJavaScript動作仕様として、JSONのパラメータとして渡された値はvalue内へ格納されますので、このスクリプト内に対してはユーザ名とパスワードを渡してあげる形になります。

```
{
	"user": "Admin",
	"password": "zabbix"
}
```

条件は整いました。
zabbix_test.jsとJSONパラメータを使用してzabbix_jsを実行してみましょう

```
$ zabbix_js -s zabbix_test.js -p '{"user": "Admin", "password": "zabbix"}'

{"jsonrpc":"2.0","result":true,"id":1}
```

はい、無事に実行できました!

# トラブルシュート

スクリプト内の動作として、正しく動いているかのアウトプットってほしいですよね？
ZabbixのJavaScriptは、「Zabbix.Log」を使用する事でzabbix_server.log(zabbix_proxy.log)への出力を行うことができます。
zabbix_jsを使用した場合は、ログへの出力は行わずに標準出力されます。
試しに、パラメータとして受け取った値がvalueへ格納されているかを見てみましょう。

``` zabbix_test.js
try {
    var req = new CurlHttpRequest(),
    params = JSON.parse(value),
    fields = {},
    res = {},
    token;

    Zabbix.Log(5, 'value : '+value);

....
    Zabbix.Log(3, 'Zabbix webhook failed : '+error);

    result = {};
}
```

「Zabbix.Log(5, 'value : '+value);」を追加してzabbix_jsを実行しても何も出力されませんよね?
これは、Zabbix.Logの第１パラメータがログの出力レベルを表していて、最高ログレベルの拡張デバッグ（Trace）モード状態で出力するという事になります。
この状態をzabbix_jsで再現する為には以下を指定します。

```
$ zabbix_js -s zabbix_test.js -p '{"user": "Admin", "password": "zabbix"}' -l 5
zabbix_js [2928]: DEBUG: In zbx_es_init_env()
zabbix_js [2928]: DEBUG: End of zbx_es_init_env():SUCCEED 
zabbix_js [2928]: DEBUG: In zbx_es_compile()
zabbix_js [2928]: DEBUG: End of zbx_es_compile():SUCCEED 
zabbix_js [2928]: DEBUG: In zbx_es_execute() param:{"user": "Admin", "password": "zabbix"}
zabbix_js [2928]: TRACE: value : {"user": "Admin", "password": "zabbix"}
zabbix_js [2928]: DEBUG: zbx_es_execute() output:'{"jsonrpc":"2.0","result":true,"id":1}'
zabbix_js [2928]: DEBUG: End of zbx_es_execute():SUCCEED 
zabbix_js [2928]: DEBUG: In zbx_es_destroy_env()
zabbix_js [2928]: DEBUG: End of zbx_es_destroy_env():SUCCEED 

{"jsonrpc":"2.0","result":true,"id":1}
```

デバッグ(Debug)モード以上を指定すると、Zabbix上の実際に実行した関数も表示されるので、ソースを追いかけるにも良いですね！
他にも、-pオプションのかわりに-iを指定し作成したjsonファイルを渡す事や-tオプションでタイムアウトの指定をするという事もできます。

---- 
地味に役立つzabbix_js、ぜひ活用してみてください。