ログファイルを監視してslackに通知する
仕事で使った
準備
通知用にincoming webhookの設定をする
↓のURLからURLを発行する
通知用のrubyスクリプト
※4/21追記
いろいろ勘違い等があり、紆余曲折あって↓のように変更した
nanka.hateblo.jp –ここまで
使用したrubyのバージョン
$ ruby -v ruby 2.0.0p648 (2015-12-16 revision 53161) [x86_64-linux]
require 'net/http' require 'uri' require 'json' uri = URI.parse("https://hooks.slack.com/services/*/*/*") text = ARGV[3] if File.pipe?(STDIN) || File.select([STDIN], [], [], 0) != nil then text ||= STDIN.read end exit unless text payload = { text: text, channel: ARGV[0], username: ARGV[1], icon_emoji: ARGV[2] } Net::HTTP.post_form(uri, { payload: payload.to_json })
こんな感じで使える
ruby slack.rb "#room" "name" ":ghost:" "hoge" echo "hoge" | ruby slack.rb "#room" "name" ":emoji:"
tail,grepと組み合わせて特定のログが書き込まれた際にslackに通知
ワンライナーにしてtmux上で動かしている
tail -n 0 -F logfile | grep --line-buffered "hoge" | while read i; do ruby slack.rb "#room" "name" ":emoji:" "$i"; done
tailの挙動がよくわからずに、ここまで作るのに結構時間がかかってしまった
以下はいくつかハマった?ポイント
監視対象が毎日貼り変わるシンボリックリンクだった
当初 tail -f
しか知らなかったので、貼り変わった時どうしようか少し悩んでしまった
-F
オプションにすることで、リネームされたときやシンボリックリンクが貼り変わった時でも自動で追従してくれる(らしい)
grepした結果が通知されない
tail -n 0 -F logfile | grep "hoge" | while read i; do ruby slack.rb "#room" "name" ":emoji:" "$i"; done
としてると全然通知されなかった
grepに --line-buffered
オプションを付けることで問題は解決した
どうやら出力バッファリングという機能が邪魔をしていたらしい
tail -Fの結果をパイプで渡すとruby側で上手に捌けない..?
tail -Fが特殊な挙動をすることが原因だと思いこんでいるが、
tail -F logfile | ruby slack.rb "#room" "name" ":emoji:"
とすると、どこかのタイミングで標準入力がない状態で↓のif文が通ってしまい、STDIN.readでキーボード入力待ちになってしまう場合がある
if File.pipe?(STDIN) || File.select([STDIN], [], [], 0) != nil then text ||= STDIN.read end
そこで while read i
で一度受け取るようにしたら、正しく動くようになった
tail -F logfile | while read i; do ruby slack.rb "#room" "name" ":emoji:" "$i"; done
原因がわからないのが気持ち悪い、いつかtailの実装を読んでみたい
※4/21追記
原因については↓
nanka.hateblo.jp –ここまで