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

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版
詳解システム・パフォーマンス

Goツールのクロスビルドとパッケージングのためのgoxzというツールを作った

Goツールのクロスビルドと成果物生成には個人的に長らく、goxcを愛用していましたが、その乗り換えとして、goxzというのを作った。go + x(cross) + z(zip)でgoxz。便利です。

https://github.com/Songmu/goxz

goxcは非常に高機能なのですが、僕がその機能の一部しか必要ないことや、goxcのメンテ自体も止まっている(とオフィシャルでも案内されている)ことが気になったので作りました。

具体的には「Goツールのクロスビルドと成果物のアーカイブ生成をパラレルにおこなう」ことしかしない。アーカイブ生成時に、リポジトリからLICENSEやREADMEを自動的にかき集めるのはやってくれます。

基本的には「設定より規約」という感じで、良い感じのデフォルトを決め打ちにして、あまり細かい設定項目などは作らない想定です。

インストール

https://github.com/Songmu/goxz/releases に生成物があります。homebrewのFormulaも用意しました。お好きな方法でインストールしてください。

% brew install Songmu/tap/goxz
% ghg get Songmu/goxz
% go get github.com/Songmu/goxz/cmd/goxz

使いかた

Goプロジェクトのリポジトリ直下で以下のようにすれば、./dist ディレクトリ以下に生成物が配置されます。

% goxz -pv=1.0.1 -os=darwin,linux -arch=amd64 -d=dist ./cmd/mytool
% tree ./dist
dist/
├─ mytool_1.0.1_darwin_amd64.zip
└─ mytool_1.0.1_linux_amd64.tar.gz

後は、みんな大好きghr を使えば、GitHub Releasesに成果物をアップロードできます。

% ghr 1.0.1 ./dist

補足など

成果物配置ディレクトリ内の事前クリーンナップ処理はおこないませんので、ビルド前に整理するか、新規ディレクトリを指定するなどしてください。配置ディレクトリが存在しない場合の新規作成はgoxzはおこないます。

成果物の名前に、バージョン情報を含みたくない場合は、-pvオプションを指定しなければそうなります。

圧縮方式は、windowsとdarwinでzip、それ以外がtar.gzが標準となっていますが、-z オプションを使うことで圧縮方式をzipに統一することができます。

Mackerelプラグインパッケージの作成に利用する

goxz はMackerelプラグインパッケージ作成にも利用可能です。Mackerelプラグインパッケージは、ファイル名にバージョン情報を含まず、また、zipであることが期待されているため、以下のように指定すると良いでしょう。

# mackerel-plugin-hoge 配下で
% goxz -os=darwin,linux,windows -arch=amd64 -z
% tree ./goxz
goxz/
├─ mackerel-plugin-hoge_darwin_amd64.zip
├─ mackerel-plugin-hoge_linux_amd64.zip
└─ mackerel-plugin-hoge_windows_amd64.zip

後は、先にも述べたとおり、ghrを使って、GitHub Releasesにアップロードするのが簡単でしょう。

ぜひご利用ください

単純に比較するのはフェアではないですが、goxcのコードベースが8000行を超えているのに対し、goxzはテスト込みで600行程度ですので、見通しも良いと思います。

goxzを作るにあたって、goxcを参考にした部分もあります。特にコマンドラインオプション設計などは参考になり、改めてgoxcは良くできているな、と思ったりしました。

goxz は既に goxz 自体のビルドに使われています。僕の身の回りのツールも徐々に乗り換えていく予定です。

Goツールの成果物をGitHub Releasesに上げるときのこれからの定番は、goxz + ghr ってことで一つ。

ということで、ぜひご利用ください。機能要望やpull requestもお待ちしています。

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

https://github.com/Songmu/horenso/releases/tag/v0.1.0

変更点は以下の通りです。

Result JSONへの signaled フィールドの追加

以前のバージョンでは、対象のプロセスがシグナルで停止したかどうかを、終了コードが128以上かどうかで判別していましたが、本バージョンでは、プロセスがシグナルで停止したかどうかを正確に判断するようにしました。それに伴い、 signaled フィールドをResult JSONへ追加し、シグナルで停止された場合にこのフィールドに true がセットされるようになりました。signaledtrue の場合、そのシグナルナンバーは exitCode - 128 で求めることができます。

ちなみに、Goでコマンドの実行エラーから終了コードを取得するためのサンプルコードがネット上に散見されますが、殆どが、意図してのことかもしれませんが、シグナルが考慮されていません。そのあたりの話はそのうち別途書きます。

アーカイブの命名規則の変更

これは実はミスで、リリーススクリプトを整備したら以前と非互換な命名規則になってしまいました。実際社内のプロビジョニングもコカしてしまう羽目になってしまった…。今後は現状の命名ルールにそろえていく予定です。

以上ご活用ください。

えるしっているか、Lは便利

Perl Advent calendar 2017の6日目です。

LというCPANモジュールがありまして、これはPerlのコマンドラインワンライナーを書きやすくするためのモジュールです。

% perl -MString::Random -E 'say String::Random->new->randregex("[0-9a-z-A-Z]{12}")'

あるモジュールを読み込んでクラスメソッドを呼び出したい時には、上記のように、モジュール名を2回打ち込まないといけないのが難点ですが、それを以下のように書くことができる。

% perl -ML -E 'say "String::Random"->new->randregex("[0-9a-zA-Z]{12}")'

便利。

このモジュールは僕が5年前にCPANに上げたモジュールなのですが、Perl 5.27.1で失敗するテストケースがあり、今年それを直すとともに、バージョンv1.0.0としてリリースしました。

それが補足されて、少し話題になったようで、今年のYAPC::Fukuokaの際に、 @nqounet さんに「最近Lを知ったんですけど、すごく便利ですね」と言っていただきました。ということで、ここで改めて紹介してみることにしました。

L というトップレベルかつ1文字モジュールということで、2012年当時、これをCPANに上げるかどうかはかなり躊躇したのですが、周りのPerl Hackerの皆様に後押ししてもらって上げました。

反響を心配していたのですが、好意的なレビューもついて、一安心したことを覚えています。思い出深いモジュールです。

go-memcached-toolを書いていた

はてなエンジニア Advent Calendar 2017の3日目です。 昨日は、id:y_uuki さんによるウェブシステムの運用自律化に向けた構想 - 第3回ウェブサイエンス研究会でした。

さて、memcachedにはmemcached-toolというツールが同梱されています。

https://github.com/memcached/memcached/blob/master/scripts/memcached-tool

これを、今回(実は大分前に書いていたのですが)、Goに移植しました。

https://github.com/Songmu/go-memcached-tool

以下のようにインストール可能ですが、GitHub Releasesにも置いてあります

% go get github.com/Songmu/go-memcached-tool/cmd/go-memcached-tool

memcached-toolは、memcachedの作者であり、今はGoのメインコミッターの一人であるBradfitz氏の書いたPerlスクリプトなのですが、これを僕がGoに移植したというのがちょっと面白ポイントです。

memcached-toolにはいくつか機能がありますが、今回は、よく使われる、memcachedのslabの状態とかをいい感じに表示してくれる display モードと、memcachedのデータをダンプする dump モードを移植しました。

memcachedのslabとは何ぞやとか、memcached-toolの使い方は以下の記事によくまとまっています。

参考: 第2回 memcachedのメモリストレージを理解する:memcachedを知り尽くす

memcached-toolと同様ではありますが、軽く使い方の説明を。

displayモード

memcachedの各slabの状態を良い感じに表示してくれます。

% go-memcached-tool 127.0.0.1:11211
  #  Item_Size  Max_age   Pages   Count   Full?  Evicted Evict_Time OOM
  1      96B  17550349s       1   10922     yes  1121115        0    0
  2     120B  17529950s       3   26214     yes  2693486        0    0
  3     152B  17656340s       2   13793     yes  1262170        0    0
  4     192B  17652024s       2   10917     yes   139583        0    0
  ...

dumpモード

memcachedの内容を書き出すことができます。

% go-memcached-tool 127.0.0.1:11211 dump > memd.dump

以下のようにすれば、あるサーバーのキャッシュをゴソッと別サーバーに移すことができるのが面白いですね。実際にはこんな乱暴なことはしないとは思いますが。

% go-memcached-tool 127.0.0.1:11211 dump | nc cache2.example.com:11211

その他のモード(stats/settings)について

オリジナルのmemcached-toolには statssettings と言ったモードがありますがこの辺は以下のようにすれば同じようなことができるので特に移植予定はありません。

% echo "stats"          | nc 127.0.0.1 11211
% echo "stats settings" | nc 127.0.0.1 11211

ライブラリとして使う

以下のようにライブラリとしても利用可能です。Goでmemcachedをモニタリングするようなツールを書く際に有用でしょう。

import (
    "net"
    "github.com/Songmu/go-memcached-tool"
)
func main() {
    conn, _ := net.Dial("tcp", "127.0.0.1:11211")
    items, err := memdtool.GetSlabStats(conn)
    ...
}

コマンドラインツールを書く時に、その言語のライブラリとしても再利用可能にすることは個人的に心がけている点です。実は、このgo-memcached-tool自体、mackerel-plugin-memcachedの拡張用のライブラリとして利用するために書き始めた背景があります。

ぜひご利用ください。