【Fluentd】in_execプラグインを使ってみる


## in_execプラグインとはなにか
外部のスクリプトを定期的・恒久的に実行し、スクリプトの標準出力を読み取る機能を提供するプラグイン。サードパーティ製ではなく、Fluentdに標準で組み込まれている。
詳細は[公式マニュアル](http://docs.fluentd.org/articles/in_exec)参照。

## 使ってみる
まずは、実行対象の外部スクリプトをRubyで適当に作る。
ファイル名はsample.rbとし、/tmp以下に配置する。

```ruby
# sample.rb
print '{"one": 1, "two": "2", "three": ["a", "b", "c"]}';
```

次にfluentdの設定ファイル（/etc/td-agent/td-agent.conf）を以下のように編集する。

```
# INPUT
<source>
  type exec
  tag in_exec_test

  # 実行するコマンド
  command ruby /tmp/sample.rb

  # commandで指定した外部スクリプトの出力フォーマットをjsonに設定
  format json

  # 5秒毎に実行する
  run_interval 5s
</source>

# OUTPUT
<match in_exec_test>
  type file

  # 以下のファイルに出力する
  path /tmp/in_exec_test.log
</match>
```

td-agentを再起動する。

```
$ sudo service td-agent restart
Shutting down td-agent:                                    [  OK  ]
Starting td-agent:                                         [  OK  ]
```

OUTPUTプラグインによる出力結果を確認する。

```
$ tail -f /tmp/in_exec_test.log.20141121.b508590dabae46c41
2014-11-21T19:09:34+09:00       in_exec_test    {"one":1,"two":2,"three":"san","four":["a","b","c"]}
2014-11-21T19:09:39+09:00       in_exec_test    {"one":1,"two":2,"three":"san","four":["a","b","c"]}
2014-11-21T19:09:44+09:00       in_exec_test    {"one":1,"two":2,"three":"san","four":["a","b","c"]}
.
.
.

```

設定通り5秒毎に出力されている。
出力内容もスクリプトで実行した結果そのまま。

### TSV形式でも実行してみる
in_execはJSON、TSV、MessagePackの3種類のフォーマットに対応しているようで、もう1つくらい試してみたいと思ったのでTSV形式でもやってみる。

まず、/tmp/sample.rbを以下のように編集する。

```ruby
print "foo\tbar\tbaz";
```

/etc/td-agent/td-agent.confも編集する。

```
# INPUT
<source>
  type exec
  tag in_exec_test

  # 実行するコマンド
  command ruby /tmp/sample.rb

  # commandで指定した外部スクリプトの出力フォーマットをtsvに設定
  format tsv

  # TSV形式の場合はkeysにkey名を指定する必要がある
　keys one,two,three

  # 5秒毎に実行する
  run_interval 5s
</source>

# OUTPUT
<match in_exec_test>
  type file

  # 以下のファイルに出力する
  path /tmp/in_exec_test.log
</match>
```

td-agentを再起動する。

```
$ sudo service td-agent restart
Shutting down td-agent:                                    [  OK  ]
Starting td-agent:                                         [  OK  ]
```

OUTPUTプラグインによる出力結果を確認する。

```
$ tail -f /tmp/in_exec_test.log.20141121.b508590dabae46c41
2014-11-21T19:19:15+09:00       in_exec_test    {"one":"foo","two":"bar","three":"baz"}
2014-11-21T19:19:20+09:00       in_exec_test    {"one":"foo","two":"bar","three":"baz"}
2014-11-21T19:19:25+09:00       in_exec_test    {"one":"foo","two":"bar","three":"baz"}
.
.
.

```

keysで指定したone、two、threeがそれぞれJSONデータのキー名になっていて、sample.rbのタブ区切りでの出力内容が順番に値になっている。

### 【番外編】formatをJSONに指定しつつ、JSONでないデータを出力した場合にどうなるか
個人的に少し気になったので試す。
source.formatにjsonと指定しつつ、スクリプトではTSV形式の出力を行ってみる。

というわけで設定ファイル（/etc/td-agent/td-agent.conf）だけ編集する。

```
# INPUT
<source>
  type exec
  tag in_exec_test
  command ruby /tmp/sample.rb
  format json
  run_interval 5s
</source>

# OUTPUT
<match in_exec_test>
  type file
  path /tmp/in_exec_test.log
</match>
```

再起動。

```
$ sudo service td-agent restart
Shutting down td-agent:                                    [  OK  ]
Starting td-agent:                                         [  OK  ]
```

ログを見る。

```
$ tail -f /tmp/in_exec_test.log.20141121.b508590dabae46c41
.
.
.
```

何も出力されていない。
fluentd自体のログにエラーが出力されていないか見てみる。

```
$ sudo tail -f /var/log/td-agent/td-agent.conf
2014-11-21 19:28:17 +0900 [error]: exec failed to run or shutdown child process error="lexical error: invalid string in json text.\n                                       foo\tbar\tbaz\n                     (right here) ------^\n" error_class="Yajl::ParseError"
  2014-11-21 19:28:17 +0900 [warn]: /usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems/fluentd-0.10.55/lib/fluent/plugin/exec_util.rb:39:in `parse'
  2014-11-21 19:28:17 +0900 [warn]: /usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems/fluentd-0.10.55/lib/fluent/plugin/exec_util.rb:39:in `call'
  2014-11-21 19:28:17 +0900 [warn]: /usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems/fluentd-0.10.55/lib/fluent/plugin/in_exec.rb:124:in `run_periodic'
```

めっちゃエラー出てた。5秒毎に出てるし当然か。
出力されているフォーマットがJSONじゃないぞって感じで怒られている。

この後、設定は元に戻しました。
以上、in_execを使ってみたまとめでした。