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

「UNIXという考え方」における「沈黙は金」は常に正しいか

みんな大好き「UNIXという考え方」に「沈黙は金」という項目があって「コマンドが成功した場合には余計な出力をすべきではない」ということが書いてあります。

ユーザーに会話調で話しかけることがユーザーを助けることだ、と考えているプログラマが多すぎる。UNIXは一般に「ドライ」で、ただ「事実」だけを伝える。

まず、この項目はこの本の中では「10の小定理」というものの中に含まれるもので、小定理については必ずしも常に正しいとは限らないというような注意書きが書かれていることを先に断っておきます。

コマンドラインツールはデフォルトでは余計な出力をすべきではないというのは基本同意です。詳細な途中経過のログを流したいのであれば、 --verbose オプションが実装され、それが利用されるべきでしょう。それに最近作られたツールは出力を出し過ぎで煩わしく感じることも多くなってきました。

ただ、それは少し偏屈な技術者の思考じゃないのかとも思うようにもなりました。とっつきやすさのために、少しだけフレンドリーなログを出してあげるのもアリなのではないでしょうか。実際、初めてコマンドラインを触ったとき、あまりにもぶっきらぼうでとっつきづらいと感じる人がほとんどでしょう。 svc とか初めて触ったときビビりませんでしたか?

なので、標準ではログを吐きつつ、 --silent オプションで出力を抑制するようなパターンもありだと思います。

ただ、ここで大事なのは「ログ的な出力には必ず標準エラー出力を使う」ということです。標準出力は他のプログラムに受け渡されうるデータを出力する目的のみに利用すべきだからです。これは、定理9の「すべてのプログラムをフィルタにする」にも書かれていることで、これは完全に正しいです。

ところで、最近Go製のツールによくあるんですが、 --help の出力が標準エラー出力に出るのはページャーに渡しづらくてめんどくないすか? 2>&1 | less とかやるのがダルい。これは「明示的にヘルプ出力が望まれているのだから標準出力に出すべき」派です。

UNIXという考え方

git-set-mtimeをリリースしました

https://github.com/Songmu/git-set-mtime

ローカルファイルとディレクトリのmtimeをgitの最新コミット日時に書き換えてくれるツール。rosylillyが作っていたやつを以前から使わせてもらっていたのだけど、それをforkしたままバイナリリリースもしました

% go get github.com/Songmu/git-set-mtime

でもインストール可能です。オリジナルに対する変更点は以下のとおりです。

特にruby版削除は大きな変更になってしまうので、fork側で別途メンテナンスさせてもらうことにしました。ライセンスなどは元のライセンスを残しつつ適宜アップデートしているつもりですが、変なところがあったらご指摘ください。

たまに便利です。ご利用ください。

blogsync v0.9.1をリリースしました

https://github.com/motemen/blogsync

はてなブログ用の便利コマンドラインツールであるところの、blogsync v0.9.1をリリースしました。最近は日本語READMEを載せたり、バイナリリリースも作ってあるので便利にご利用いただけます。

直近の大きなアップデートは以下のとおりです。

omit_domain によるダウンロードパスの変更

omit_domain という設定項目が追加されました。この設定をオンにすると、そのブログをダウンロードしてきた際に、ダウンロードパスにドメインが含まれなくなります。

yourblog.example.com:
  local_root: /path/to/myblog
  usename: xxx
  ...

例えば、上記の設定ですと、 /path/to/myblog/yourblog.example.com/ 配下にblogの内容がダウンロードされます。

このとき、 yourblog.example.com/ というディレクトリが掘られてしまうのですが、それが煩わしい場合は、 omit_domain の出番です。

yourblog.example.com:
  omit_domain: true
  local_root: /path/to/myblog
  usename: xxx
  ...

このように、omit_domain を設定すると、 /path/to/myblog/ 直下にブログをダウンロードできます。

設定ファイルの読み込みの改善

blogsyncは、ローカル設定(./blogsync.yaml)とグローバル設定(~/.config/blogsync/config.yaml)の2つの設定ファイルを持つことができます。

最新バージョンでは、ローカル設定とグローバル設定に同じブログドメインが設定されている場合、その設定がいい感じにマージされるようになりました。同一の設定キーが設定されている場合は、ローカル設定が優先となります。

まとめ

実は、Mackerel の各種ドキュメントは、はてなブログを利用しており、版管理のためにblogsyncとGitHubを組み合わせています

というように、blogsyncは一部ではかなり実績のあるツールですのでぜひお試しください。

もう少しテスト書くなどして、バージョンv1.0.0を出したいと考えています。

DBIx::Sunny 0.9991をリリースしました

https://metacpan.org/release/SONGMU/DBIx-Sunny-0.9991

みんなだいすき、安全安心のkazeburo wareであるところのDBIx::Sunnyですが、この度、バージョン0.9991をリリースしました。pull requestを送りまくっていたら、コラボを頂いたといういつもの流れです。

最近の大きな更新は以下の通りです。

特にNamed placeholderはアツくて、以下のようにクエリ発行系のメソッドの第2引数にhashrefを渡すと利用できます。便利。

$dbh->select_all('SELECT * FROM users WHERE id IN (:ids) AND status = :status', {
    ids    => [1,2,3],
    status => 'active',
});
#SQL: 'SELECT * FROM users WHERE id IN (?,?,?) AND status = ?'
#@BIND: (1, 2, 3, 'active')

内部的には、cho45氏作のSQL::NamedPlaceholderを利用しています。このモジュールは、はてなブログ内部でも開発当初から利用されていることもあり、長らく実績のあるモジュールなので安心してご利用いただけます。

最近大きめのリファクタリングを入れたので、一旦0.9991というバージョン番号で出してますが、しばらくおいて問題なさそうならバージョン1.0000を出そうと考えています。

より便利になった、DBIx::Sunnyをぜひご利用ください。

ちなみに、Perlでversion.pmを使わないでバージョン宣言をする場合、小数点以下は4桁にするのが良いんじゃないかと最近は考えています。ちなみにPlackもそうなってました。

それは、Perlのバージョン番号の変換ルールの仕様で、マイナーバージョンとパッチバージョンは小数点以下3桁ごとに区切られるからです。

つまり、0.9991は、v0.999.100と等価です。パッチバージョンをまともに3桁割り当てると、小数点以下6桁になって見づらくなってしまうので4桁にするのが穏当なのではないか。

ところで、version.pmを使わないでバージョン宣言をするのは、そのモジュールがPerl5.8系をサポート対象とする場合の話で、Perl5.8系を切り捨てて良いのであれば、素直に、version.pmを使ったほうが良いでしょう。

IoT時代の自宅ネットワーク

タイトルは釣りです。IPv6の話とかも出てきません。以下の様な話です。

OCNからNuro光に乗り換えた

10年近くOCNを使っていたのをNuro光に乗り換えた。自宅のマンションでキャンペーンやってて簡単に乗り換えられそうだし、大分安くなるので契約した。

ただ、正直、ブロッキング問題がなかったら今回の変更には至らなかったと思う。

ネット回線は金額よりも品質のほうが大事なのでこれまで選定はコンサバに振ってたし、それでOCNの回線には大きな不満もなかった。乗り換えることで品質がどうなるかは未知数でリスキーであることもあり、単に安くなるだけだったら今回の乗り換えにはいたらなかったと思う。

なので、ブロッキング問題が今回の背中を押すきっかけにはなったと思う。ただ、そこまで強いポリシーを持っているわけでもないので、キャンペーンをやってなかったらそのままOCNを使い続けていたと思う。

当たりルーターを引いた

Nuro光が回線工事時に持ってくるルーターは何種類かあるのだが、それを指定することはできない。工事が終わった後に別のやつに変えてもらうように手配をすることはできるらしい。ただし有料。

今回は、運良く当たりルーターを持ってきてもらうことができた。高速無線通信可能なIEEE802.11ac対応のEchoLife HG8045Qという新モデル。

もう一つ、ZXHN F660Aという、IEEE802.11ac対応の新しいルーターがあるのだけどこっちが来ていたらかなり困ることになって危なかった。というのも、こちらは同時接続機器数が10台なのだ。

ご家庭のIP機器の多さ

10台あれば充分と思われるかもしれないが、実は全然充分ではない。僕が職業柄多めだというのもありそうだが、とはいえガジェッターでもないのでメチャクチャ多いわけでもないと思う。以下に書き出してみる。

実に17台。全部が常時つながってるわけではないが、それでも10台では全然足りない。

ということで、今や色々なものが簡単にインターネットに繋がる時代なので、家庭内でもIPを持っている機器は想像しているよりずっと多い。ルーターのIP払い出し一覧を眺めていてびっくりした。家庭ですらこの有様なのですからオフィスネットワークはマジで大変そうですね…。

エンジニアHubに「Goらしさ」についての記事を寄稿しました

「Go言語らしさ」とは何か? Simplicityの哲学を理解し、Go Wayに沿った開発を進めることの良さ

こちら寄稿させていただきました。

「Goらしさ」についての記事を書いて欲しいという依頼を受けたときは、正直これはかなり身に余るなと思いました。同僚のid:motemenを始め、これを書くのにもっと相応しい人がいるように感じたし、難易度も非常に高いので。恐れ多さがすごい。

断ろうとも思ったのですが、依頼を受けているうちが華だというのもあるので、頑張って受けることにしました。妻には「なんでそんな執筆受けちゃったの…?」と詰められました。

案の定執筆は難航し、ストーリーが降りてくるまで本当に時間がかかった。編集の方々は、色々スケジュールを融通いただいて本当にありがとうございました。

なんとか原稿が書き上がり、評判も上々で一安心というところです。まだ未読の方でGoに興味ある方はぜひご覧ください。この度はいい機会をいただきまして、本当にありがとうございましたという気持ちです。

JSONを使ってコマンドラインを動的に組み立てて実行するjfillを作った

https://github.com/Songmu/jfill

標準入力からJSONを受け取り、その値を使ってコマンドラインを組み立てて実行するユーティリティです。以下のような具合です。

インストール

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

もしくはGitHub Releasesからご利用ください。

使い方

% echo '{"name":"jfill"}' | jfill echo Hello {{name}}!
Hello jfill!

{{name}} の部分がプレースホルダーです。それがJSONの入力を元に置換され実行されています。

プレースホルダー内には以下のようにデフォルト値を指定することも可能です。

% echo '{}' | jfill echo Hello {{name:jfill}}!
Hello jfill!

{{name:jfill}} のコロン以降の"jfill"の部分がデフォルト値です。プレースホルダーにデフォルト値が指定されておらず、置換対象のキーがJSON内に存在しない場合、jfillは失敗します。

深い構造のJSONに対応するために、プレースホルダー内にXPathのような文字列を指定することができます。内部的には github.com/mattn/go-scan を利用しています。

% echo '{"Songmu":{"age":38}}' | jfill echo Songmu is {{/Songmu/age}} years old.
Songmu is 38 years old.

作った動機

主にMackerelのチェック監視で、引数を動的に指定させる仕組みが欲しかったのが動機。何らかのパラメーターストアとjfillと連携させれば動的に引数を指定できます。以下はmackerel-agent.confのサンプル。

[plugin.checks.unicorn-worker]
command = '''
  echo '{"threshold":'$(getconf _NPROCESSORS_ONLN)'}' \
  | jfill check-procs -P unicorn --critical-under={{threshold:5}}
'''

少しわざとらしい例ですが、この場合、CPUコア数よりもワーカー数が少なくなった時にアラートが上がります。JSONが正しく出力できなかったときにエラーになるのを防ぐためにデフォルト値を指定するのが推奨です。

ConsulのKVSやMackerelのmetadata APIと組み合わせるのも賢い方法です。ちなみにMackerelのmetadata APIを利用する際に毎分アクセスするのは効率が悪いため、何らかのキャッシュ機構を使うことを強く推奨します。(お願いします…!

環境変数を動的にセットしたい場合

env コマンドと組み合わせると良いでしょう。

% echo '{"lang":"ja_JP.UTF-8"}' | jfill env LANG={{lang}} date
2018年 6月12日 火曜日 01時27分28秒 JST

fillinとの違い

https://github.com/itchyny/fillin というものがありまして、僕も便利に使っているのですが、ユースケースが違うため、別で作ることにしました。

まとめ

ぜひご利用ください!仕組み上、結構危ないことができてしまうため、ご利用は計画的に!

あわせて読みたい

WEB+DB PRESS Vol.104 の Perl Hackers Hubに「Minillaを使ったモダンなCPANモジュール開発」という記事を寄稿しました

記念すべきPerl Hackers Hub第50回にMinillaに関する記事を寄稿させてもらいました。Minillaは、日本国内ではデファクトとなっているCPANモジュールのオーサリングツールですが、まだ案外Perl Hackers Hubで取り上げられてなかったので、書かせてもらうことにしました。

WEB+DB PRESS Vol.104

Minillaはその作法に従えば非常に高速にCPANモジュールの開発が可能です。逆にお作法に従わないと躓いてしまうこともあるため、それらを丁寧に解説し、誰でもMinillaでCPANモジュール開発ができるようになることを目指した記事になっています。

内容は、Minillaを使ってモジュールを開発してCPANにアップロードするまでの一通りのフローの解説と、それに加えて社内モジュールのようなプライベートモジュールを開発時にMinillaを利用する方法について取り上げています。特にCPANモジュールのファイル配置ルールや、依存ライブラリの自動抽出に関しては力を入れて書きました。

Minilla解説の決定版とも言える内容となっております。案外知られていないこともあると思うので是非お手にとってみてご確認ください。

今回、牧さんのレビューにはかなり助けられました。特に初稿の段階では内容を詰め込もうとするあまり、ストーリがすっ飛んでしまっており、牧さんの的確な指摘のもとストーリーを肉付けすることができました。

また、稲尾さんの全体の進行や編集は非常にスムースで快適に執筆をおこなうことができました。4年前に執筆させていただいた時も十分にやりやすかったのですが、更に進化しており「快適」とも言えるレベルになっていたのは驚きました。

GitHub上のプライベートリポジトリ上でMarkdownで原稿執筆をおこなうのですが、まず、稲尾さんが注意書きを含めたプロジェクトの雛形一式をpushするところから始まります。あとは、稲尾さんが的確なタイミングで各執筆フェーズに対応するissueを挙げ、それにレビュアーや筆者が対応し、issueが全て閉じられるとなんと執筆が完了しているという具合でした。

さて、Minillaは基本的にはコンフィギュレーションフリーで使えますが、細かい設定を工夫することにより多くのユースケースをカバーでき、かゆいところにも手が届く作りになっています。今回の記事でもう少しそれらの細かいユースケースに対しても取り上げ、解説したかったのですが、とりとめもなくなってしまうので削ったものがあります。例えば以下の様なものがありますが、そのうちどこかで解説するかもしれません。

ghr 0.9.0をリリースしました

https://github.com/tcnksm/ghr/releases/tag/v0.9.0

GitHub Releasesに手軽に成果物をアップロードできる、みんな大好きghrですが、最近deeeetさんが忙しく、メンテが滞っていたこともあり、僕もメンテに加わらせてもらうことにしました。

ghrは僕個人として常用させてもらっている他にも、Mackerelのプラグイン作成時にも利用を推奨しています。今回取り込んで欲しいpull requestがあったため、メンテ権をいただくことにしました。

そのあたりのpull requestを諸々マージして、ghr v0.9.0をリリースしました。0.5.4からジャンプアップ気味ですが、そろそろ1.0.0を見越してもいいのかなと言う気持ちです。

今回一番大きな変更点は、リリースがアトミックになったことです。これが今回入れてほしかった変更です。

これまでのghrでは

  1. リリースを作成する
  2. そのリリースに対して成果物をアップロードする

という手順になっており、1と2の実行間でlatest releaseを取得しようとした場合、そのリリース中のバージョンを取得してしまい、正しく成果物を取得できない可能性がありました。これを以下のように変更しました。

  1. リリースをDraftとして作成する
  2. そのリリースに対して成果物をアップロードする
  3. リリースのDraftを解除する

これで、最新のリリースを取得した際に、必ず必要な成果物が含まれている状態を保証できるようになりました。

また、成果物のアップロード失敗時に2回までリトライするようになったことも目玉の変更点です。これでより安定的にリリースをおこなえるようになります。

その他、リリースフローや依存関係のアップデートをおこないました。より安定性と信頼性の増したghrを是非ご利用ください。

homebrew formulaをどうするかはちょっと保留中です。ghtoolsというorgを取得したのでそちらに移すことも考えています。1つのツールに1つのformula repoを作るのもどうなのかという気持ちもある。ご意見ください。

2017年振り返りと2018年の所信表明

2018年になって暫く経った。はてなは半期末が1月なので、年明けに半期末がやってくる感じになっててマネージャーにとっては慌ただしい。その後体制変更などがありあっという間に4月になった。

2017年は2016年にも増して慌ただしい1年だった。3月に育休が取れたのは良かったけど、それ以外な必死になってしまって余裕のない一年だったように思う。

対外的な発表とかOSS的な活動とかが少なかったのは反省点。

書籍「Mackerel実践入門」が出せたのは良かった。はてなに入ったときに意識していたことは「技術を作る側に回る」ということだったので、それがある程度体現できたのは良かった。「ある程度」って言ったのは、まだまだやりたいことがあるということ。今年は単著が書けると良いんだけど、ちょっと無理かもしれない。

Mackerelが新たな時系列データベースを開発できてプラットフォーム移行できたのもめでたかった。これで次の成長の可能性が大きく増したことになる。

その他、良かった点としては、YAPCとかMackerel関係で、地方に行って色々なエンジニアと交流できたこと。福岡では、YAPCでもMackerel関連のイベントでも、 @pyama さんにはお世話になりました。ありがとうございました。

あとは、採用が結構順調なことも良い点。エンジニアもいい人が採用できている。エンジニアの他にもハイクラスのマネージャー層の人が何人か入ってきているのも良くて、違う畑の人に学ばせてもらう部分も多く、そういう優秀な人と働けることにワクワクしている。

この4月で、はてなに入って3年7ヶ月が経った。自分のキャリアの中で一番長く務めた会社ということになる。最近何のために、はてなに入ったのか今、改めて考え直している。そうすると、やはり、Mackerelを成功させることと、はてなという会社を技術ブランディングの点で盛りたてることにあると思う。

Mackerelという技術は面白い、監視やインフラ管理は面白い。これは多くのエンジニアが思っている以上に面白いものだ。これは僕自身もMackerelに関わってわかったことで、もっと周りに伝えていきたいと思っている。

技術ブランディング的には、僕自身は、技術力がそれほど高くない割には、インターネット上ではプレゼンスがあることに常々課題意識があって、プレゼンスに溺れないように、もっとストイックに技術を追求したい気持ちがもともとある。ただ、その意識が強くなって勢いが弱くなってしまっていたことが反省点。

そこは開き直って、僕自身が、はてなの技術ブランディングの上で必要な人間という自覚を持って、プレゼンスに偏ってるのは自分の特性としてなりふり構わず活かしていこうと思っている。それを通して、社内の隠れた技術力が高いエンジニアを社外にアピールしていく役割も果たしたい。

去年良かった本

ピクサー流 創造するちから
反応しない練習
Real World HTTP
ふつうのLinuxプログラミング 第2版
詳解システム・パフォーマンス