おそらくはそれさえも平凡な日々

ghchを利用してGoツールのリリースを自動化する

ghch v0.0.2 をリリース しました

CHANGELOG.md を見るとわかりますが、以下の様な変更が入っています。もちろんこの CHANGELOG.md はghchで生成しています。

このバージョンから、リリーススクリプトを整備して、スクリプト一発で以下のことができるようになりました。

実際のスクリプトはこれ → https://github.com/Songmu/ghch/blob/master/_tools/releng

ちなみに、Goのプロジェクトでこういうスクリプトってどこに置くのがいいのだろうか。go toolが無視してくれたほうが良さそうなので、一応アンダースコアをつけた _tools に配置をしているのですが。

ということで、今後Goツールのリリースはこういう感じでやっていこうと思います。

Mac上にGoの開発環境を構築する〜下準備編

同僚がGoを始める上で、案外まとまった資料が無さそうだったので書いてみることにしました。

Macでhomebrewが入っていることが前提です。事前に brew update をおこない formula を最新のものにしておくと躓くことが少ないでしょう。

Goのインストール

% brew install go

エントリ執筆時点では、1.6.2 が入ります。Goはメジャーバージョンが同じ場合は、後方互換が保たれているので、基本的に新しいやつを入れて問題ありません。

環境変数の設定

$GOPATH だけを決めればOKです。$GOPATH はどこでも良いのですが、ここでは $HOME/dev$GOPATH に設定します。また、 $GOPATH/bin$PATH も通しておきます。

export GOPATH=$HOME/dev
export PATH=$GOPATH/bin:$PATH

今後Goの開発は全て $GOPATH 配下でおこなうことになります。

go getしてREPLを入れてみる

$GOPATH を設定すると go get ができるようになります。試しにGoのREPLである、gore を入れてみましょう。

% go get github.com/motemen/gore

ついでに gore の真価を発揮させるために、以下のパッケージも併せて入れましょう。

% go get github.com/nsf/gocode
% go get github.com/k0kubun/pp
% go get golang.org/x/tools/cmd/godoc

ちなみに、 go get には -u というオプションがあります。このオプションをつけないと、手元のパッケージが古くても更新をしてくれません。最新の状態にしたい場合には go get -u を使うようにしましょう。

さて、これでおもむろに gore とターミナルに打ち込んで起動すれば go get 成功です。

% gore
gore version 0.2.5  :help for help
gore>

Ctrl+dで終了します。

gore は非常に便利で、特にGoに慣れないうちは、挙動の確認のために欠かせないツールです。

詳しくは作者のエントリをごらんください。 → コード補完もできる Go の REPL「gore」を作った

$GOPATH の中を覗いてみる

さて、go get をしたら $GOPATH がどうなったかを見てみましょう。

% ls $GOPATH
bin/    pkg/    src/

$GOPATH 直下を見てみると、3つのディレクトリがあります。bin/ にはGo製ツールの実行ファイルが、src/ にはソースコードが配置されます。

src/ 以下を掘り下げて見てみましょう。

% tree -L 3 $GOPATH/src
$GOPATH/src
├── github.com
│   ├── k0kubun
│   │   └── pp
│   ├── mattn
│   │   └── go-colorable
│   ├── mitchellh
│   │   └── go-homedir
│   ├── motemen
│   │   ├── go-quickfix
│   │   └── gore
│   ├── nsf
│   │   └── gocode
│   └── peterh
│       └── liner
└── golang.org
    └── x
        └── tools

{{vcs_domain}}/{{repositry_path}} というような形で配置されていることがわかります。

Goは、GitやMercurialなどのリポジトリがパッケージになるという面白い特徴があります。また、 go get で取得したソースコードには、GitやMercurialの履歴も含まれています。そのため、開発もその中でおこなうことができるのです。

ghq を使いリポジトリ管理をより簡単にする

$GOPATH/src のリポジトリ配置ルールは、最初は慣れないが、実は理に適った配置です。

僕は、Go言語以外の全てのプロジェクトリポジトリも $GOPATH/src 配下に配置するようにしています。そこで役立つのが ghq です。

ghqgo get と同様のルールでソースコードリポジトリを取得するためのツールです。homebrewでインストールできます。

% brew install ghq

インストールが終わったら、 ghq でソースを取得してくるディレクトリを以下のように指定します。

% git config --global ghq.root '~/dev/src'

これで準備は完了です。ここで ghq list と打つとリポジトリ一覧を取得してくれます。また、ghq get <target> とすることで、リモートリポジトリのソースコードを取得できます。

はかなり柔軟に指定ができて賢い振る舞いをします。例えば、以下のように、各種URLやGitHubのパスなどを指定しても、柔軟に解釈して、ダウンロードしてくれます。

# 例
% ghq get git://hogehoge.git
% ghq get https://github.com/mackerelio/mackerel-agent
% ghq get mackerelio/mkr

これで、手元のソースコードリポジトリの管理を簡単におこなうことができるようになりました。

ghq についても作者のエントリを参照してみてください。 → ghq: リモートリポジトリのローカルクローンをシンプルに管理する (ちなみに、リンク先で言及されている ghq import は現在は削除されています)

peco でより便利にリポジトリの移動を行う

さて、これで統一感の取れたリポジトリ管理ができるようになりましたが、$GOPATH/src 配下の階層が非常に深くなってしまい、そのままだと移動が面倒です。そこで peco を使います。

peco はターミナル上で標準入力を行ベースでインクリメンタルにフィルタするUIを提供する、汎用性の高いツールです。これもまたhomebrewでインストールが可能です。

% brew install peco

peco がインストールされたら、早速 ghq と組み合わせて使ってみましょう。お使いのシェルがzshの場合、以下の様な設定を、.zshrc などに書いてみてください。

bindkey '^F' peco-src

function peco-src () {
    local selected_dir=$(ghq list | peco --query "$LBUFFER")                                        if [ -n "$selected_dir" ]; then
        selected_dir="$GOPATH/src/$selected_dir"
        BUFFER="cd ${selected_dir}"
        zle accept-line
    fi
    zle clear-screen
}
zle -N peco-src

peco-src という関数を定義し、それを Ctrl+fで呼び出せるようにしてあります。

この設定を読み込んだ後に、ターミナル上で、Ctrl+fを入力するとpecoのUIが現れます。そこで適当にキー入力をおこなうと、フィルタリングされていく様子が見て取れるでしょう。

例えば、私の環境で、 github mackerel- という条件でフィルタしている様子が以下になります。

ここで、適当なリポジトリを選択し、エンターを押して確定すると、そのディレクトリに移動することができます。

これで、go getghq getしたリポジトリに自由に移動できるようになりました。

peco のその他の活用例は、公式のWikiのSample-Usage を見ると良いでしょう。

まとめ

これで、Goで開発をおこなう下準備は整いました。エディタ設定や、実際にプロジェクトを開始するときにどうするかなどは、そのうち書くかもしれません。

Gitのtagとpull requestのマージ履歴からChangelogを自動生成する `ghch`

https://github.com/Songmu/ghch

mackerel-agent のリリースフローでは、前回のリリース以降の、pull requestのマージ履歴を拾って、そこからChangelogを自動生成するということをおこなっている。

これは、1年半前くらいにPerlで書いていたのだが、この度汎用的にしてGoで書きなおした。それが ghch。前回打ったsemverっぽいgit tag以降のマージ履歴を抽出してくれる。例えば、こういう風にmackdownで出力がされる。

% ghch --format=markdown --next-version=v0.30.3
## [v0.30.3](https://github.com/mackerelio/mackerel-agent/releases/tag/v0.30.3) (2016-04-27)

* retry retirement when api request failed [#224](https://github.com/mackerelio/mackerel-agent/pull/224) ([Songmu](https://github.com/Songmu))
* Fix comments [#222](https://github.com/mackerelio/mackerel-agent/pull/222) ([stefafafan](https://github.com/stefafafan))
* Remove go get cmd/vet [#223](https://github.com/mackerelio/mackerel-agent/pull/223) ([itchyny](https://github.com/itchyny))
* [nit] [plugin.checks.foo ] is valid toml now [#225](https://github.com/mackerelio/mackerel-agent/pull/225) ([Songmu](https://github.com/Songmu))
* Remove usr local bin again [#217](https://github.com/mackerelio/mackerel-agent/pull/217) ([Songmu](https://github.com/Songmu))
* Fix typo [#221](https://github.com/mackerelio/mackerel-agent/pull/221) ([yukiyan](https://github.com/yukiyan))

標準だとjsonが出力される。そっちのほうがスクリプトからだと扱いやすいでしょう。

コミットログをChangelogの代わりにするというのは流石に乱暴だろうと僕は思っているので、サマリーとしてのChangelogは必要。ただ、書くのは面倒くさいので、マージしたpull requestのタイトルを拾ってきてそれをChangelogの一覧にするのは結構良いんじゃないかと思っている。

pull requestのタイトルであれば後から編集ができるので、Changelog生成前に見なおして書きなおすことも簡単。コミットログだとこうはいかず、後から編集が面倒くさいし、そもそも歴史改変もしたくない。ちなみにmackerel-agentの場合だと、 [nit] というタグがタイトルについていれば、Changelogに載せない、みたいな運用もしています。

gobump やgoxc、ghrと併用すれば、CHANGELOG自動更新を含めてリリース作業を自動化することも可能でしょう。

ちなみにマージコミットを拾う仕組みになっているので、squash mergeボタンを使ってしまうと抽出できないので注意。

以下からバイナリを取得できます。ぜひお試しください。

https://github.com/Songmu/ghch/releases

禁酒することにした

先月中頃から禁酒していて、7回飲み会行って酒を飲まないことに成功しているので、禁酒成功している。

飲み会自体は変わらず行くけど酒は頼まない。祝い酒とか食前酒とかそういうのは別に拒まず飲むくらいの緩い運用でやっております。

特に何があったというわけでないのだけど、唐突に思い立って止めようと言う気になった。

ここ数年酒は十分楽しんだなーという感じでもう飽きた感じもある。

最近、飲み会が多くて、飲み始めると無限に飲んでしまうので、流石にブレーキをかけるかというのもあった。僕は欲望を満たし始めたら徹底的に満たすことがモットーで、中途半端に飲んで我慢するのは嫌なので、完全にやめてしまうか、というところ。

最近は、完全に惰性で飲んでいて、身体もヤバいし、欲望に溺れている感じがあった。欲望を好きなだけ満たしつつ、欲望には溺れないというところがモットーなのに完全に失敗していた。

ということで、しばらく飲まない予定です。最初にも書いたけど飲み会には行くよ!

コミュ力が無いのはいつだって自分

突然何を言い出すのかという話ですが、対話相手にコミュニケーション能力を求める醜さについて書きたくなったので書きます。

僕はオタクだったしスクールカーストで言うと下の方を彷徨ってきた。地元でもいろいろあって浮いていた。新卒時の就活も散々だった。なので、コミュ力がないことは自覚しているし、だからこそ「コミュニケーション能力」という言葉には警戒心があります。

比較的マイノリティであったことが多かった経験上分かったのは、相手とコミュニケーションが取りづらいな、と思うときは、そもそもプロトコルが異なる、ということです。

これは、話している自然言語が違うようなものだと考えるとわかりやすい。例えば、自分が日本語しか話せず、相手がロシア語しか話せないのであれば、まともなコミュニケーションが成り立たないのは明らかです。そして、その時に、日本語が話せない相手にコミュ力がないと思うような人はいないでしょう。

それが、実際のコミュニケーションになると、不思議と相手のコミュ力不足を断じるような人がでてきます。

例えば「最近の若者はコミュ力が云々」みたいなのは、老害が若者語を話せず、若者は老害語を話したくもない、というだけの話でしかありません。同様にリア充が非コミュを見下すのも、リア充が非コミュ語を話せず、非コミュがリア充語を話せないという話でしか無いのです。

もちろん、それぞれのプロコトルを使いこなして、それぞれのクラスタの人とうまくコミュニケーションが取れる人もいる。そういう人はマルチリンガルみたいなもので、コミュ力が高いと言えるのは間違いない。

ただ、コミュニケーションが取れない時に、それを相手のコミュ力のせいにするのは知性と人間性の欠如でしかありません。一般的に何らかの問題が起こっているときに、それを自分のせいにするか、相手のせいにするかで、その人の知性や人間性が試されます。

自分をマジョリティだと思っている人、コミュ力があると勘違いしている人は、普段は自分の周辺の大半の人とのコミュニケーションには困らないので、自分と違うコミュニティの人と意思疎通ができなかった時には相手のコミュ力を見下しがちです。

ただ、自然言語に置き換えると、別に言語話者の多寡はコミュ力とは関係ないのは明らかです。日本語話者より中国語話者の方がコミュ力が高いと言われて納得できる人はいないでしょう。

それに、コミュニケーションが取れない以上、自分の方が多数派だとは限りません。相手は、サンスクリット語を話しているかもしれないし、ヒンディー語を話しているかも知れません。ヒンディー語話者は身近には居ないかもしれませんが、世界的には日本語の5倍くらいの話者がいます。

実際、コミュニケーションが全く成り立たない人、というのもいます。ただそれは、自分と相手のプロトコルの問題であって、どちらかのコミュ力の高低の問題ではない。そう僕は考えるようにしています。相手とコミュニケーションが取れるか取れないかという事実だけがあり、それをどう捉えるか、という話です。

じゃあ、人間はコミュニケーションプロトコルが近しい人とだけコミュニケーションを取っていればいいかというと、そういうわけではないと考えています。

異質なものとコミュニケーションを取っていかないと変化や成長はありません。身近な人と慣れ合っていても成長が望めないというのはその裏返しです。生物の交配と同じような話で、長い目で見ると生き残れなくなる可能性があります。

また、コミュニケーションは、コストとリターンの話でもあります。相手とコミュニケーションを取るためにこちらがどれくらいのコストを払い、どれくらいの見返りが得られるか、ということです。これは相手にとっても同じです。

だから、お互いが支払うコストに対して、リターンが多いという合意が取れた場合に、健全なコミュニケーションが成り立つと言えます。

一般的に、コミュニケーションプロトコルが近い相手とのコミュニケーションは、ローコスト・ロー(〜ミドル)リターンです。そして、それが遠い相手とは、遠くなるほどコストは高くなり、リターンは未知数です。

まず、お互いのプロトコルが違いすぎて、お互いのリターンが見込めない時、むしろマイナスになりそうな時は、意識的に関わらないようにすることも大事です。これはすごく大事。

そして、お互いのプロトコルが異なりつつも、リターンの期待値を上げたい場合には、自分からコミュニケーションを取りに行くことが大事だと思ってます。

コミュニケーション能力があるとみなされている人は、ここが上手い。僕なんかは、そうやったほうがいいと思っても躊躇してしまってなかなかできなかったりするのです。ただ、少なくとも、コミュニケーションが取れない理由を相手のせいにしないで歩み寄ることを心がけていて「コミュ力が無いのはいつだって自分」だと思うようにはしています。

いろいろな人とコミュニケーションが取れるようになると、色々なプロトコルを操れるようになって、コミュニケーションの精度も上がっていくのでしょう。自然言語の習得とかも近い話であるようにも感じます。

なんでこういうこと書いたのかというと、採用とかマネージメントに関わるようになって、コミュニケーションってなんだろうなーとか考えたりすることが増えた影響が大きそう。

Webアプリケーションエンジニアにこそ薦めたい「ITインフラ監視[実践]入門」

ソフトウェアエンジニアのための ITインフラ監視[実践]入門

技術評論社様よりご恵贈頂きました。著者のkoemuさん、ありがとうございます。

この本は本当に監視入門にふさわしく、以下のように網羅的かつ、そして何より陳腐化しない、普遍的な監視に対する心構えや考え方に対して非常によくまとまっていました。

監視に対する心構えや、「監視システムをどのように運用していくか、閾値をどのように決めていくか」、そして、なかなか無い観点として「監視体制の業務設計」といった話が印象深かったです。

モデルケースとして、Linuxサーバー上のApache、MySQL、Tomcatの監視などが取り上げられており、実際に Mackerel!!!を使った監視構築にも触れられており非常に興味深くも嬉しくも思いました。

あまり監視の知見のないWebアプリケーションエンジニアが、自分が作ったサービスを一般公開したものの、監視に対する知見がなくて困っていたり、アプリケーションは作れるようになったが、実際に運用していく中でどういった心構えが必要なのか知りたい、といったケースに本書は非常に有用だと思います。

また「監視とは何なのか」という観点の本は珍しく、監視とは何なのかを改めて考えるきっかけにする意味で、実際に業務でバリバリ監視を行っている人であっても、本書を読むことをおすすめしたい。

ソフトウェアエンジニアのための ITインフラ監視[実践]入門

「nginx実践入門」は紛うことなき「実践」の本だった

nginx実践入門

技術評論社様よりご恵贈頂きました。著者の1人である cubicdaiya さんより、いただけるというお話をもらった時は非常に光栄でした。ありがとうございます。

思っていたとおり非常に良い本でしたが、特に良かった点としては、章立てを含めた構成の素晴らしさ、そしてまさに「実践」を意識したインフラアーキテクチャの本になっている点だと思う。

という章立てになっていて、流れが非常にわかりやすい。Nginxを軸にした、様々なインフラのデザインパターンの説明になっている。これは紛うことなき「実践」の本であり、イマドキのインフラアーキテクチャについて学ぶ上でも良本である。

静的ファイル配信、リバプロ構成、コンテンツ配信システム、それぞれの構成において重要になるディレクティブが事細かに説明されており、非常に分かりやすかった。得てしてこういった設定項目を説明するときは、リファレンス的な退屈な羅列になりがちで、逐次読んでいく分には頭に入ってこないものだが、この本は、対象とするアプリケーションと、その場合に必要になってくるディレクティブがセットで語られており、非常に理解しやすいものになっていた。

リバプロ構成では、PHPやUnicornとの連携について語られていたり、モニタリングの章ではfluentdやNorikra、Growthforecastを絡めたインフラ構成について語られており、単なるNginxだけにとどまらない、実践的なインフラアーキテクチャについて深い知見が載っていたように感じる。

個人的には第5章のhttpsに関する章が、改めて読むと、ちゃんと理解していない所だらけで、非常に学びがあった。

第6章の「Webアプリケーションサーバーの構築」に関しては、 try_files ディレクティブを積極的に使っている点が少し気になった。 try_files はトリッキーなので、意図せずアプリケーションサーバーにリクエストが飛んでしまい、要らぬ負荷をもたらしたり、どこでエラーレスポンスを返しているか追いづらくなるので、個人的には使わないに越したことはないと思っている。ただ、局所的に必要になる場合はあるだろうとは思っていて、ものすごく重いリクエストを一時的にファイル配信に差し替えたい、となった場合に try_files にしておくことは有効なのかもしれない。特にpixivさんのような重いコンテンツ配信が多いシステムだと、その傾向がより強いのかもしれない。

第7章の「打規模コンテンツ配信サーバーの構築」はよりpixivさんっぽくて面白かった。普段あまり関わりのないシステム構成の話なので面白く読めた。

第9章のnginx_lua、第10章のOpenRestyのところは、非常に興味深かったし勉強になった。ただ、個人的にはもう少し実例を含めて掘り下げて欲しかったように感じる。ただ、対象ユーザーとか、分量的な部分で仕方なかったんだろうなーとか思います。

Nginxは今やスケーラブルなWebシステムを構築する上で欠かせない存在になっており、その中で本書は、様々なパターンに対する実例を示した実践的な良書であると思う。Nginxを知りたいというだけでなく、現代的なインフラアーキテクチャを知りたい、という人にも是非オススメしたい。

nginx実践入門

より良い `go run` を実現する goshim

https://github.com/Songmu/goshim

プロジェクトでちょっとしたスクリプトを書いてリポジトリで共有したいとなった時に、スクリプト言語なら楽ですが、Goで書くのはやや面倒です。リポジトリを分けるようなものでもないし、わざわざ go install させるようなものでもないけど、ビルドしたバイナリをどこに置くのかなどが悩ましい問題です。macを使っている人もいればlinuxを使っている人もいるのでバイナリをリポジトリに配置するわけにもいきません。

go run でも良いかと思われるかもしれませんが、本当にちょっとしたものならよいいのですが、以下の様な問題があります。

そこで goshim の出番です。 goshim は指定したパッケージディレクトリのコードをビルドしてキャッシュし、それを exec で実行してくれます。それにより、 go build したバイナリを実行するのと同様にGoのソースを実行することができます。

以下のようにインストールします。

% go get github.com/Songmu/goshim/cmd/goshim

そして、以下のように呼び出します。

% goshim ./script/ore/pkg [args...]

これで、プロジェクトリポジトリに雑にGoのツールのソースコードを突っ込んでも、 goshim で雑に動かしてもらうことができるようになりました。

make のようにソースコードの mtime を見ているため、コードが更新されていない場合にはキャッシュが使いまわされ、高速に実行できる点もポイントです。

ビルドが必要であっても、ビルド自体に多少は時間はかかりますが、動き出してしまえばGoのバイナリを実行しているのと同じことになるので、ちょっとしたコードを雑にデプロイするのにも便利かもしれません。

go run main.go とかやるよりも goshim . の方が短いのも見逃せません。

実行にはgoの環境が必要であり、開発者のためのツールという感じなので、バイナリは提供しない予定です。普通に go get してみてください。作ってみたら思いの外便利だったので、皆様も是非ご活用ください。

goshimsyscall.Exec() を使っているので windowsで動きません。またmattnさんに怒られてしまいそうです。

horenso v0.0.1 をリリースしました

https://github.com/Songmu/horenso/releases

以下の点が変更になっています。特に一番上が大きな変更です。

今後JSONにキーを追加する可能性はありますが、互換は崩さない予定です。よろしくお使い下さい。

horensoというcronやコマンドラッパー用のツールを書いた

リリースしました

https://github.com/Songmu/horenso

cron等、バッチジョブを走らせた場合にその結果通知やエラーレポートをどうするかは悩ましい問題です。ラッパースクリプトを統一的に噛ますのが常套手段ですが、そのためのツールとして、horenso というものをGoで作りました。報・連・相。その名の通り、実行ジョブの報告をつかさどってくれる君です。以下のようにして使います。

% horenso -r reporter.pl -- /path/to/job args...

-- 以降に指定したコマンドが実行され、その結果がJSONとして標準入力経由でreporterに渡されます。reporterは実行可能なファイル、もしくはコマンドライン文字列であり、記述言語は任意です。reporterに渡されるJSONは以下の様なものです。

{
  "command": "perl -E 'say 1;warn \"$$\\n\";'",
  "commandArgs": [
    "perl",
    "-E",
    "say 1;warn \"$$\\n\";"
  ],
  "output": "1\n95030\n",
  "stdout": "1\n",
  "stderr": "95030\n",
  "exitCode": 0,
  "result": "command exited with code: 0",
  "pid": 95030,
  "startAt": "2015-12-28T00:37:10.494282399+09:00",
  "endAt": "2015-12-28T00:37:10.546466379+09:00"
}

JSONには、実行したコマンドと、その出力、エラー出力、マージされた出力や終了コード、開始時間と終了時間など含まれています。その情報を利用して、ログを残したりチャットなどへの通知処理をおこなうと良いでしょう。

時間のかかるジョブを実行するときなど、ジョブ開始時に通知をしたいこともあるでしょう。そのために -n(--noticer)というオプションがあります。

% horenso -n 'ruby noticer.rb' -r reporter.pl -- /path/to/job args...

ジョブ開始直後にnoticerが呼び出されます。noticerの引数にも、上記のJSONが一部埋まっていない形で渡ってきます。pidは埋まっているため、それを使って開始と終了を突き合わせることもできるでしょう。

また、reporterなどのハンドラーは複数指定することが可能です。その場合、ハンドラーは並行実行されます。Goっぽいですね!

% horenso -r reporter.pl -r reporter2.py -- /path/to/job args...

horenso をcronで利用する場合、そのままcrontabに書くのではなく、ラッパーシェルを作ってその中で呼び出すのが良いでしょう。例えば以下の様な具合です。

#!/bin/sh
exec /path/to/horenso \
  -n /path/to/noticer.py         \
  -r /path/to/reporter.pl        \
  -r 'ruby /path/to/reporter.rb' \
  -- "$@"

このようなシェルスクリプトを例えば wrapper.sh という名前で保存し、crontabの中で以下のように利用します。

3 4 * * * /path/to/wrapper.sh /path/to/job --args... 2>&1 | logger -t myjob

horenso は、コマンド自体の出力を奪うことはせずそのまま出力するため、上記のように logger コマンドをつかってsyslogに出力している場合でもこれまでどおりログをtailすることが可能です。また、コマンドの終了コードも上書きされることなく、そのまま保持されます。

コマンドの実行結果の通知処理を変更したい場合でも、ラッパースクリプトそのものをいじる必要がなく、reporterやnoticerを変更すれば良いだけなので、ラッパースクリプトをぶっ壊してしまう心配が無いのが安心です。疎結合になっている分、ハンドラーの単体テストもしやすくなっていると言えるでしょう。

reporterを工夫することで、

などの処理を柔軟におこなうことが可能になります。

簡単、便利な horenso 、是非お使いください。ビルドバイナリなどはそのうち。

追記と今後の展望

結構反応を頂き嬉しいので、タグ打ってバイナリリリースとかさっさと整えようと思っています。また、若干仕様変更が入る可能性があって、現状、JSONが引数で渡ってくるようになっていますが、引数のサイズ制限などの問題がありそうなので、標準入力経由で渡すように変えようかなーと考えています。

引数の上限は % getconf ARG_MAX で取得できるようです。勉強になりました。

余談

horenso は私の代表的プロダクト(自称)であるruncronをGoでreviseしたものです。 runcron は非常に便利なツールで私ももちろん愛用していましたが、以下の様な課題がありました。

その点を踏まえて、horenso は以下のようになりました。

また、Goだと、ハンドラーの並行実行をしたり、出力をパイプして別スレッドでメモリ上にバッファしたりが簡単にできたので、慣れるとこういうツールを書くのには向いてそうだなーと改めて思いました。

もちろん、runcron は枯れていて安定していますし、プラグイン資産がある場合はその使い回しがやりやすいので、一概にどちらが良いといえるものでもないでしょう。

あわせて読みたい