これは Ansible Advent Calendar 2017 の13日目の記事です。
ansible コマンドでログ検索
ansible コマンドって使ってますか?
Ansible と言えば普段は ansible-playbook コマンドを使うと思うので一応解説しておくと、ansible コマンドは Ansible モジュールを1個だけ実行するコマンドです。-m でモジュール、-a でそのモジュールに渡す引数を指定します。Running Ad Hoc Commands - Ansible Tips and Tricks あたりが詳しいです。
この ansible コマンドで shell モジュール を使うと、複数サーバ上のログを簡単に検索できます。
例えば以下のように、すべてのアプリケーションサーバに対して、一括で ERROR ログ数を検索できます。
$ ansible -i hosts app -m shell -a "cat /var/log/foobar | grep "ERROR" | wc -l" app1 | SUCCESS | rc=0 >> 177 app2 | SUCCESS | rc=0 >> 84 app3 | SUCCESS | rc=0 >> 37
僕の場合は wc の代わりに head を使って ERROR ログを何件か表示し、サーバごとの傾向の違いを調べることもあります。
$ ansible -i hosts app -m shell -a "cat /var/log/foobar | grep "ERROR" | head -5"
もちろん、普段の運用に必要なログは、特定のサーバやデータベースに集めておくべきです。わかってますよ、わかってるんですが、集めてないログを調べたくなるときはどうしてもあって。そういうときに ansible コマンドで手軽に検索できるのは便利です。
ansible コマンドの結果を TSV/JSON/Markdown/Backlog 形式に変換
ログを調べたら、(それが仕事なら)たいてい他の人に共有したくなるわけですが、この出力は若干使い勝手がよくありません。
Excel や Google Spreadsheet で処理するにも手作業でのコピペが必要になりますし、Wiki にそのまま貼るにも不便です。以前からこの出力がちょっと気になっていました。
そこで Go の勉強がてら、ansible コマンドの結果を他の形式に変換する ansible2tab コマンドを作ってみました。
先ほど例に挙げた出力をこの ansible2tab に通すと、以下のように変換されます。
$ ansible -i hosts app -m shell -a "cat /var/log/foobar | wc -l" | ansible2tab app1 177 app2 84 app3 37
デフォルトが TSV なので ansible2tab という名前にしましたが、--format
を指定すると JSON などにも変換できます。ちなみに、僕が仕事で使うので Backlog 記法にも対応しました。
$ ansible -i hosts app -m shell -a "cat /var/log/foobar | wc -l" | ansible2tab --format json {"app1":"177","app2":"84","app3":"37"} $ ansible -i hosts app -m shell -a "cat /var/log/foobar | wc -l" | ansible2tab --format markdown |Host|Value| |---|---| |app1|177| |app2|84| |app3|37| $ ansible -i hosts app -m shell -a "cat /var/log/foobar | wc -l" | ansible2tab --format backlog |Host|Value|h |app1|177| |app2|84| |app3|37|
出力が複数行の場合はうまく表になりません。その場合は --format markdown-code
や --format backlog-code
と指定すると、以下のようなコードブロックに変換します。
できることはこれだけの、地味なツールです。でも、個人的には日常業務で結構こういうことしてるんですよね……。
この ansible2tab コマンドですが、Mac なら brew 経由でインストールできます。
$ brew tap muziyoshiz/ansible2tab $ brew install ansible2tab
それ以外の環境では リリースページ からダウンロードしてパスを通すか、あるいは Go の開発環境があれば以下のコマンドでインストールできます。
$ go get github.com/muziyoshiz/ansible2tab
まとめ
ansible コマンドは、複数サーバ上のログを手軽に検索するには便利です。今回は、このログ検索した結果を TSV/JSON/Markdown/Backlog 出力する ansible2tab を作りました。Go で実装したおかげで、さくっとクロスプラットフォーム対応できました。
世間に似たようなニーズがどれくらいあるかわからないですが、よかったら使ってみてください。別の形式にも対応して欲しい、JSON はもっと違う形式がいい、などの要望は GitHub の Issue か @muziyoshiz までお願いします。
あと、Go 初心者なのでコードがあまりイケてないと思います。そのあたりのツッコミも歓迎です。
今回の参考情報
Go 言語全般
- 作者: 松木雅幸,mattn,藤原俊一郎,中島大一,牧大輔,鈴木健太,稲葉貴洋
- 出版社/メーカー: 技術評論社
- 発売日: 2016/09/09
- メディア: 大型本
- この商品を含むブログ (4件) を見る
Go のコードに詰まってから読み返すと、ヒントになることが書いてある(と気づく)本でした。良い本です。
以下、今回参考にさせて頂いた Web 上の情報です。
- Golangで自分自身で定義したパッケージをインポートする方法あれこれ - Qiita
- 序盤に詰まったところ。僕は「その1(推奨)」の方法でやりました
- 外部テストパッケージの利用ケース #golang - Qiita
- testing パッケージでのテストの書き方
- package pflag
- 短縮形のオプション(
--format
に対する-f
)をサポートするために、標準の flag の代わりに使用
- 短縮形のオプション(
- Go言語でinterfaceをimpleしてるつもりが「does not implement (method has pointer receiver)」って叱られる【golang】【pointer】【ダックタイピング】 - DRYな備忘録
- Formatter interface を定義し、ここから各形式のフォーマッタ(例:TSV に対応する TsvFormatter)を実装しようとしたときにつまづいたポイント
バイナリの配布方法
- golang勉強会でGo製ツールの配布方法について話してきた | SOTA
- @deeeet さんのまとめスライド
- これを見て gox を使うことに決めました
- 高速に自作パッケージをGithubにリリースするghrというツールをつくった
- GitHub の release ページへのアップロード方法
- HomeBrewで自作ツールを配布する | SOTA, tcnksm/ghr, tcnksm/homebrew-ghr
- brew での配布方法
- 今回は、@deeeet さんの記事とコードにお世話になりっぱなしでした
- Goツールのリリースにおけるバージョニングについて - おそらくはそれさえも平凡な日々
- gobump を使おうとしたのですが、僕の手元ではバイナリがインストールされなくて、今回は諦めました