ISUCON7決勝に参加してきました@チームinarisan

ということで、参加して、負けてきました。

isucon.net

正直、全然スコアのびず。

初期スコアが5000点位に対して、最終スコアが13600点くらい。人権は失っていませんが、仕事ができた感がありませんorz

優勝チームが65000点くらい、2位チームが28000点位、優勝チームが飛び抜けていますが、20000点超えたチームもそこそこいたみたいなので、全然だめでした。

お題は、クッキークリッカーをソーシャルライクに(みんなでクリックできるように)したもの。

ポイントは、アプリケーションによるサーバー4台に対する振り分け(いわゆるゲームのチャンネルシステムみたいなもの)と、ウェブソケットを使った通信の中でのアプリケーション改善。

できなかったことは大量にあるので、やったことくらいは記録に残しておきます。自分はアプリケーションメインなので、アプリケーションのことだけ。

やったこと

①ルームごとにサーバーの振り分けを矯正して、負荷をならしつつ、サーバーごとにデータストアを持てるように変更。

ルームの振り分けは1サーバーに集中させて、そこのデータストアで振り分けを管理するから、グローバルなデータストアは不要。(本当はここからインメモリ化しないといけない)

②ステータスの更新処理を0.5秒ごとから0.8秒ごと(くらい)に遅くする。ステータスは1秒以内にルーム内のユーザーに同期されれば良いので、おそくしちゃう。

(けど、ステータスの取得ロジックを最適化しきれなかった。)

③0.5秒なり0.8秒ごとに取得する必要があるステータスをキャッシュ化させる。

してみたけど、キャッシュの仕方が悪かったり、失効タイミングが微妙だったりで、ベンチマーカーのチェックに引っかかってしまう。

ということで

モニタリング、プロファイリング、などなど、問題点を見つける部分をもっと勉強する必要があります。

というか、全然わかってない、ということがわかった。

ブレブレだけど記念撮影しました。LINEやKlabの皆さまや運営に携わられてた皆さま、ありがとうございました。

f:id:sugilog:20171125204007j:plain

ISUCON7参加しました@チームinarisan

ISUCON7の予選に参加しました。

今回参加したチームはチームinarisanです。ギリギリですが本戦出場!!終了1時間前までは諦めが強かったですが、何とか挽回しました。

isucon.net

運営の皆さま、お疲れ様でした。スコアが伸びずに苦労しましたが、その分、学びも多くて問題を解くことを楽しめました。

来月もよろしくお願いします!

チームメンバー

@lukesilviaさん(会社の2年先輩)と@mashanさん(会社の1年先輩)と自分 @sugilog

2015年にもISUCONに同じチームメンバーで参加していて、そのときは予選突破→決勝で撃沈、という感じ。ちなみにそのときのチーム名はチームhammerでした。

今回は、役割をちゃんと意識したり、分担したわけではないですが、ざっと↓の感じに。

@lukesilviaさんが経験豊富なプログラマーなので、全体チェックとDBまわり。

@mashanさんは普段はインフラ管理されているので、OSとかDBとかの設定、nginxでのキャッシュとか、足元の部分を全部。

自分 @sugilogはコードばっかりいじってました。今回用意されたサーバーにログインしたのも10回もないはず。最後はmemcacheと格闘してました。

実装言語

rubyの参考実装から修正をすることにしました。理由はふだん使っているのがrubyだから。

僕個人は最近はGoとNode.jsを扱うほうがおおいのですが、それでも実装スピードはrubyのほうが速くて、チームメンバー3人共あつかえるほうがいいので、やっぱりruby

今回のお題だとそんなに言語に依存してパフォーマンスがブレる、みたいなことも無いんだろうと勝手に思ってますが。。。どうなんでしょ??

コードは恥ずかしいので晒しません。最後にmemcacheと格闘した実装が汚すぎる。

良かったこと

dstatが神:@mashanさんがずっと監視してくれてた。おかげで帯域の詰まりもちゃんと把握できてた。

動作テストをする:@lukesilviaさんがアプリケーションの動作をしっかりチェックしてくれていたので、どこがおかしくなったかに早く気づけた。

最後まで諦めない:勝負に出すぎると最後のスコアを落とすんだけど、ちゃんと積み上げでやったことは裏切らないと思う。

勝負に出るコードはすぐに戻せるようにする:ベンチマークは知らせながら、リバートしたコードを手元に用意しておく。すぐにサーバー側のコードを元に戻せれば傷が浅くて済む。

やったこと

時間軸はだいぶ適当です。記録をちゃんと残してるわけでもないので、だいぶおかしいかも。。。

最初の2時間

  • レギュレーションを読む。
  • コードリーディング。
  • OSとかDBでざっくり変えておいたほうがいい設定を変更。
  • systemctlの切り替え。
  • とりあえずのベンチマーク
  • とりあえずsleepを消す。。。消してよかった?

コード的にはN+1があるから、まずはそこからだね、と言う感じ。

アイコンが確実にボトルネックになりそうなことはわかってたけど、まだ優先順位を決められていない状態。

このときは、ウェブ2台+DB1台の構成を維持。

次の2時間?

  • N+1の解消。
  • アプリから返したアイコンをnginxでキャッシュ。

全然スコアが伸びなくて落ち込む。

次の2時間

帯域が詰まってしまう、ということでその辺を改善。

  • アイコンに対してNginxからキャッシュヘッダーを付けてみる(etag on;とか色々)。
  • ウェブを3台にしてみる。
  • イコン画像の読み込みをlocalhostのDBから読み込むために、DBをレプリケーション構成にする。

ここで5万点くらい?だった気がする。上位チームがうん十万点で争ってたから、がちで凹む。

@lukesilviaさんは予定があるので戦線離脱!!(個人的にはこの時点でプチパニック)

次の1時間

  • アプリケーションからetagヘッダーを付けて返してみる。アイコンの画像名の生成がhexdigestで計算されてたので、とりあえずそれを流用。
  • 部分的にmemcachedからデータを取得できるようにコードを変え始める。
  • ちょっとずつ再起動テストを始める。

あまり伸びず。。。

最後の1時間

  • pumaのスレッドとworkerの数を調整。結局どちらも1か2か、それくらい。
  • memcacheから可能な限りデータを引けるようにする。
  • 再起動テストをしまくる。

他チームのスコアが見えなくなったくらいのタイミングでスコアが急伸。15万点付近まで伸びる。

あれこれやって、途中微妙に鳴ったのでコードを戻して、みたいなことをして、最後の最後で215280(2017-10-22 20:58:58 +0900 JST)。

正直、運が良かった、というところが大きい気がします。

npm run xxx で設定ファイルを切り替える

誰得な内容なのかわかりませんが、とりあえず僕には必要だったので、まとめます。

nodeの設定ファイル内でのタスク定義は、読みづらさはあるけど、意外となんでもできる、そんな印象です。

やりたいこと

  • nodejs + npmな環境。
  • gulpなどのタスクランナーは使わない。
  • 設定ファイルが2つある。(例:config.abc.jsonconfig.xyz.json
  • 参照される設定ファイルの名前は決まっている。変更はできない。(例:config.json
  • コマンド1つでどちらかの設定ファイルを読み込む形で実行したい。

あらためて書き出すと「何なんだこれ」という感じの条件。でもしょうがない。

サンプルコード

Switch Config by arg at package.json for npm run.

ポイント

  • テンポラリな関数を作って、それを実行する、という形にする。
  • 関数名で終了する形(例:f() { ...; }; f)で書いておくと、関数名にnpm run switchの後のコマンドライン引数を付けて実行してくれる。
  • 設定切り替えは、コマンドライン引数の1つ目にしておく。その引数は、設定の切り替えだけに使って、本体のプログラム(例:node index.js)には渡さない。(shiftする。)
  • 設定切り替え用意外の残りの引数は$@で本体のプログラム(例:node index.js)に渡す。

今回の例ではシンボリックリンクで設定ファイルを固定の名前に変更していますが、必要に応じてcpとかにしないとイケない場合も有りえます。

実行ログ

実行環境

% node --version
v6.7.0

% npm --version
3.10.3

abcを使う。

% npm run switch abc

> Switch!@1.0.0 switch (省略)
> f(){ ln -s config.json{.$1,}; shift; node index.js $@; rm config.json; }; f "abc"

[]
{ a: 1, b: 2, c: 3 }

xyzを使う。

% npm run switch xyz

> Switch!@1.0.0 switch (省略)
> f(){ ln -s config.json{.$1,}; shift; node index.js $@; rm config.json; }; f "xyz"

[]
{ x: 1, y: 2, z: 3 }

登山で使っているクッカーのメスティンをコーティングしたので使ってみました

f:id:sugilog:20170225192456j:plain

前回のブログの続き。

sugilog.hatenablog.com

最初に載せた写真は、山と食欲と私で最初にメスティンが出てきたときに作っていた「オイルサーディン丼」。

山と食欲と私 1 (BUNCH COMICS)

山と食欲と私 1 (BUNCH COMICS)

オイルサーディン丼はさておき、コーティングしたメスティンを使ってみたので、レポートです。ざっくりまとめると、きれいに使えました、ということです。

なお、自分は花粉症なので、今回は自宅炊飯です。スギ花粉の時期を超えたら、山に持っていきます。

内面フッ素樹脂コーティングしたメスティン

f:id:sugilog:20170226193257j:plain

吹きこぼれはつきもの。汚く焦げ付く感じはありません。

なんとなくですが、本体・フタどちらもコーティングをしたので、すこしだけフタの締まりがしっかりした気がします。

f:id:sugilog:20170226195908j:plain

フタの締まりがしっかりしたと言ってもそこはメスティン。きれいにおいしく炊けます。

f:id:sugilog:20170226201706j:plain

少しごはんの粘り気が残りましたが、これならさっと拭けば落とせるレベル。

アルミのまま使っていた頃にはご飯粒がはりついてたり焦げ付きが茶色く残ったりしてましたが(それも味なわけですが)、コーティングによってきれいに美味しく炊ける調理器に進化した感じがあります。

内面セラミックコーティングしたメスティン

f:id:sugilog:20170225185116j:plain

f:id:sugilog:20170225192319j:plain

きれいに炊けました。

f:id:sugilog:20170225193629j:plain

オイルサーディンのオイルによるところもありますが、底に張り付いたお米はありませんし、ぬめりも少なめです。

オイルくらいなら除菌シートでさっと拭いてしまえば、山なら問題ないです。むしろオイルを拭いてしまわないで、炒めモノとかそんなことに使ってしまえばいい話です。

本体内面だけでも抜群の効果がありますね。外からみると普通のメスティンとなんにも変わんないのに、炊飯をラクにしてくれる調理器、いい感じです。

改めて

個人の登山用具のコーティング加工をしようとした先人と、個人のめんどくさい依頼にも応えてくださった睦美化成さんさんに感謝です。

登山で使っているクッカーのメスティンをコーティング加工してもらいました

たまには登山のお話。といいつつ山の話ではなく道具のお話です。

最近『山と食欲と私』という漫画を読んでいます。

www.kurage-bunch.com

山と食欲と私 1 (BUNCH COMICS)

山と食欲と私 1 (BUNCH COMICS)

主人公の女の子が美味しそうにご飯を炊いている描写があって衝動買いしたクッカーがありました。

それがトランギア社製のメスティン。アルミ製の角型クッカー。

trangia(トランギア) メスティン TR-210 【日本正規品】

trangia(トランギア) メスティン TR-210 【日本正規品】

メスティンのいいところ

  • 大きさが大きすぎず小さすぎない(個人的な感覚の話)。
  • 軽量。本当に軽いです。
  • 持ち手が邪魔にならないようにたためる。
  • バックパックにしまっておくときには食事関連の荷物を入れておくにもちょうどいい角型。
  • 火加減と時間さえちゃんとすれば、美味しく炊飯できる。

自分のメインのクッカーはジェットボイルなのですが、メスティンのちょうどいい感じに、ちょっと浮気です。

メスティンのイケてないところ

  • 使い始める前にフチのバリとりが必要。(気になる方はググってください。今回はこの話題じゃないので。)
  • アルミくささ。(気にしなければ気にならない。)
  • 焦げ付きやすい。(テフロンフライパンじゃないんだから当たり前。)
  • 炊飯後の焦げ付き&粘り気は除菌シートくらいでは落としきれない。(当たり前。)

ちょっとした手間を気にしなければ、いい感じですよね(笑)

コーティング

メスティンについてちょいちょい調べていると、コーティング加工をした、という人の記事を目にします。

www.soraironote.com

itoito.style

なので、自分もやってみました。

お願いしたのはさきほどの記事の方々と同じ睦美化成さん

いろいろまとめておきます。

※内容はすべて2017年1月に、自分が依頼したときの話です。時と場合とで変わる内容があると思うのですが、それはその時の話ということでお願いします。

依頼

睦美化成さんのホームページからメスティンの加工依頼したいことをメールしてみる。 他の会社さんを調べてみたら、今は受け付けてないみたいな会社さんもあったので、そのあたりから確認です。

睦美化成さんから、メールの返信をいただきまして、早速具体的な内容をまとめてくださっています。 メールで具体的な内容をガッツリと案内いただけるので、最初に読む内容は多いですが、心配はなくなってありがたいですね。 依頼がどんな感じで進んでいくのか、把握できます。

自分は「新品のメスティン」と「数回使用したメスティン」と2つ依頼したかったのでそのあたりと加工内容を確認します。

使用済みのモノについては、状態によっては加工できないことがあるらしいとのこと。そのあたりは現物を見ていただくしかありません。

とりあえず依頼したい内容をメールで送りつつ、現物を郵送します。メスティンの取っ手は加工しないので外しておきます。

現物が睦美化成さんに届くと、確認後、最終的な見積もりと加工の承諾についてのメールが送られてくるので、そのあたり確認して返信します。

あとは待つだけ。

代引きで送られてくるので、現金用意して待ってたら、きれいに加工されたメスティンが手元に届きます。

依頼内容

かなり変則的な依頼をしました。

新品のメスティン(本体+ふた)

内面フッ素樹脂コーティング+外面セラミックコーティング。

他の方も書かれていますが、内面のフッ素樹脂コーティングは加工温度が高くてアルミ素材が柔らかくなってしまうそうです。

なので補強のためにも外面のセラミックコーティングをやっておいたほうが吉なんだそうで。

使用済みのメスティン(本体のみ)

内面セラミックコーティング+外面加工なし

セラミックコーティングは加工温度が高くないらしく、外面加工をしませんでした。

ふたは加工しなくても実はいいんじゃないかと思って、加工をしないことにしてみました。

できあがり

f:id:sugilog:20170225153410j:plain f:id:sugilog:20170225153518j:plain

新品のメスティン=内面フッ素樹脂コーティング+外面セラミックコーティング

f:id:sugilog:20170225151351j:plain f:id:sugilog:20170225151443j:plain f:id:sugilog:20170225153120j:plain

ちょっとだけ柔らかくなったような感じがありますが、荒く扱わなければ大丈夫です。コーティングをしてもフタはしっかりしまります。

使用済みメスティン=内面セラミックコーティング+外面加工なし

f:id:sugilog:20170225151532j:plain f:id:sugilog:20170225151517j:plain f:id:sugilog:20170225153045j:plain

柔らかくなった感じもないし、いいんじゃないでしょうか。

感想

まだ加工してもらった状態では使っていないので、使用した感想は別で。

まず何より、メール連絡の内容を丁寧にしていただけて、個人的にはとても安心感がありました。

コーティングして欲しい、みたいなニッチなお願いをしているとは言え、加工については素人。教えていただけるのはとてもうれしいです。

加工依頼を他でしたことはないですが、きれいにコーティングされているものを見ると嬉しさがあります。

ヨリの写真にもとりましたが、フチまできれいに加工されていることに感動です。

メスティンはフチのバリ取りが必要、ということを先に書いたのですが、つまり買ったばかりのメスティンはフチがちょっと痛い感じなわけです。

フチまで加工していただけたので、とても扱いやすくなりました。

新春座談会 このコンピュータ書がすごい 2017年版 の個人的なメモ

今回で9回目らしいです。

本については気になったものをピックアップ。本の説明についての引用は高橋さんや出版社さんが説明された内容(を大雑把にメモしたもの)。

今回も高橋さんは大量の本を紹介されていました。どうやってあれほど紹介できるようになるのやら、毎年驚きとともに感謝しています。

高橋さんと少しお話させていただいたのですが、守備範囲が広いですね。

ちなみに本のタイトルを書いたものは、気になった本=自分は読んでいない本、ということで今後読みたいメモです。


2016年のトピック::機械学習人工知能

2016年に本がたくさん出て、たくさん売れている。

エンジニア向けというよりも一般書的なところでもたくさん本がでた。

詳しい本はデータサイエンスや数学的なところの知識が必要な内容のものも多い。

コードを扱うようなものについては、Pythonで書かれているものが多い。

応用みたいな話でチャットボットの本も出ている。

機械学習プロフェッショナル』

ウェブデータの機械学習 (機械学習プロフェッショナルシリーズ)

ウェブデータの機械学習 (機械学習プロフェッショナルシリーズ)

http://www.kspub.co.jp/book/series/S043.html

基礎的な内容、応用的な内容、がシリーズの中に混在している。

ウェブ絡みの人なら、ウェブデータの機械学習を読んで見る、みたいなことをおすすめ。

ピックアップして読んでみたい。

機械学習入門』

機械学習入門 ボルツマン機械学習から深層学習まで

機械学習入門 ボルツマン機械学習から深層学習まで

コードやプログラムがでてこないで、(機械学習の)概念を理解していく本。

わかりやすい、ということで概念を学べるようなので、全く詳しくない自分的には機械学習の事始めに読みたい。

『ゼロから作る Deep Learning』

9月に発売して1月に重版。5万部。

Pythonコードを使ってコードを書いていくということなので、上の『機械学習入門』を読んだ次に、手を動かしてみたら、いい感じに機械学習関連のプログラミングを覚えていけるかも。


2016年のトピック::Python

プログラミング言語Pythonの本が多く出た。機械学習がらみのところも多そう。

2006年から発行されている『みんなのPython』が機械学習のコンテンツも増えてリニューアルされている。

Pythonからはじめる数学入門』

Pythonからはじめる数学入門

Pythonからはじめる数学入門

機械学習関連でPythonを使う、と決めてしまえば、必要になる数学もPythonを使って一緒に勉強してしまうという方法がいいのかもしれない。


2016年のトピック::クラウドアジャイル・DevOps・CI/CD・マイクロサービス

個人や組織内で足りていなかったスキルなんだけど、クラウドがでてSaaSなどで提供されるものが増えて、導入がすすめやすくなった。

DevOpsの関連でChatOpsなんかも。Slackとかを使ったもの。

クラウド関連では、OpenStackやDockerを扱った本もいくらか出ている。

パブリッククラウドの本としてはAWSとAzureの本が多めに出てるらしい。GCPはどうなんだろう?

『Cloud First Architecture 設計ガイド』

Cloud First Architecture 設計ガイド

Cloud First Architecture 設計ガイド

この本をベースに、トピックにしてみました。

特に自分が使っているのはパブリッククラウドで、でも使えているのは一部で、みたいな状態なので、全体的な話を理解するために読んでみるのは面白いかもしれない。


2016年のトピック::フィンテック、ブロックチェーン、仮想通貨

いろんなものが「フィンテック」という言葉でまとめられている。一般向けの読み物も多い。

(このあたりは興味がなさすぎで、すみません。話はちゃんと聞いてました。)


2016年でのランキング(とか)から

2016年の年間ランキングの中で2016年発売の本が入ったのは、『ゼロから作る Deep Learning』のみ。

ランキングについては、ムックなどは覗かれているという話。ランキングのルールは、あれこれ省かれてる、とのこと。

高橋さんはEmacsらしい。自分はVimです。

Go言語の本も5冊くらい出ている。

Selenium実践入門』

Selenium実践入門 ―― 自動化による継続的なブラウザテスト (WEB+DB PRESS plus)

Selenium実践入門 ―― 自動化による継続的なブラウザテスト (WEB+DB PRESS plus)

フロントエンドテストだけでなく、スクレイピングにも使われている。

自分はPhantomJSを頑張ってますが、扱いやすいものに変えていきたい。

『たのしい Ruby 第5版』

たのしいRuby 第5版

たのしいRuby 第5版

ドラスティックには変えていない。Ruby2で書き直した。

タイミングがだいぶずれてしまいますが、新版おめでとうございます!

新人研修向けの本がどんどん更新されていく。。。

『グラス片手にデータベース設計 販売管理システム編 第2版 』

グラス片手にデータベース設計 販売管理システム編 第2版 (DB Magazine Selection)

グラス片手にデータベース設計 販売管理システム編 第2版 (DB Magazine Selection)

販売管理システムについてのデータベース設計に触れている情報がなかなかない。

具体的なケースとして、データベース設計を学べるのは良さそう。販売管理システムというかなりカタイ設計が必要なものを扱っているのもうれしい。

『ブラウザハック』

ブラウザハック

ブラウザハック

ブラウザの攻撃手法をまとめた本。

これは前から気になっていた本。分厚いし優先順位をガッツリ落としていたけど、そろそろ始めなければ。

同一ドメインポリシーについて攻撃の話とかはちゃんと学んでおいたほうがよさそう。

『現場のインフラ屋が教える インフラエンジニアになるための教科書』

現場のインフラ屋が教える インフラエンジニアになるための教科書

現場のインフラ屋が教える インフラエンジニアになるための教科書

イマドキのインフラエンジニアになりたい人向け。

目次を見ると、クラウドを混ぜつつインフラのことを説明されているみたいで、個人的には勉強を進めたい。

まつもとゆきひろ 言語のしくみ』

言語をつくりたい人むけ。言語の設計にはどんな問題があってどう作っていけばいいのか。

自分は言語を作りたい人ではないのですが、興味強めです。


その他個人的に気になる本

『コンピュータシステムの理論と実装』

コンピュータシステムの理論と実装 ―モダンなコンピュータの作り方

コンピュータシステムの理論と実装 ―モダンなコンピュータの作り方

2015年の本ですが。大学で情報工学をやってなかったりして、どうしてもプログラムの裏側が理解できていないことが多いので、勉強に手を付けたい。

cronでメール以外の方法で結果を通知する

cronって便利なんだけど、結果を確認するのがめんどくさい。

メールを全部見るのも今っぽくない。

でもRundeckとか他のジョブスケジューラを使い始めると、実行時に依存するものが増えるのでそれはそれで微妙。

じゃあ、メールで送っている内容と同じようなものを別のプログラムが取得できるか、ということ。

ソースコード確認

最初に考えたのがコマンドからパイプで繋いで最後に別のプログラムが情報をとる、というもの。

標準出力、標準エラー出力は取得可能。 実行したコマンドは、、、?

実行したコマンドはパイプで繋いでる数が少なくて時間がかかればプロセスリストから見つけられるけど、なんか違う。

じゃあCronがメールの件名につけている実行したコマンドはどうやって?ということでソース(とりあえずcronie)をおってみた。

cronie.git - Unnamed repository; edit this file to name it for gitweb.

コマンドを実行してその結果のメールを組み立てる部分。

cronie.git - Unnamed repository; edit this file to name it for gitweb.

entry->cmdという形で取得しているので、内部的にcronのファイルを構造化して、それを実行中に保持しているに過ぎないということ。

ちなみにentrystruct

cronie.git - Unnamed repository; edit this file to name it for gitweb.

外部のコマンドがうまーくやるにはちょっと厳し目か。

crond

次に考えたのがcrondコマンドの実行時オプション。何か良さげなものがないか?

% man crond

途中いっぱい省略するけど、-mオプションで実行可能なコマンドを渡すと、本来メール送信用に組み立てたテキストを、標準入力に渡すよ、という感じ。

OPTIONS -m This option allows you to specify a shell command to use for sending Cron mail output instead of using sendmail(8) This command must accept a fully formatted mail message (with headers) on standard input and send it as a mail message to the recipients specified in the mail headers. Specifying the string off (i.e., crond -m off) will disable the sending of mail.

実験

検証環境

% cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)

% ruby -v
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux]

結果を受け取るプログラム

rubyで受け取ってみる。

/tmp/mail.rb

#!/home/admin/.rbenv/shims/ruby
text = STDIN.read
File.open "/tmp/stdin.mail.#{Time.now.to_i}", "w" do |writer|
  writer.puts text
end

とりあえずでこやつには実行権限も付与。

% chmod 775 /tmp/mail.rb

crondの起動時オプション

/etc/sysconfig/crondで起動時のオプションを指定できる。

# Settings for the CRON daemon.
# CRONDARGS= :  any extra command-line startup arguments for crond
CRONDARGS="-m /tmp/mail.rb"

cronのジョブ

とりあえず適当に、標準出力がちょっと長くなりそうなやつを。

/etc/cron.d/my.admin

MAILTO=sugilog@test.example
 * * * * * root /usr/bin/sar -P ALL

実行

まずはcrondを再起動

% systemctl restart crond
% ps aux | grep crond | grep -v grep

root       5948  0.0  0.0 126332  1712 ?        Ss   10:52   0:00 /usr/sbin/crond -n -m /tmp/mail.rb

cronの実行結果を確認してみる。

From: "(Cron Daemon)" <root>
To: sugilog@test.example
Subject: Cron <root@sugilog> /usr/bin/sar -P ALL
Content-Type: text/plain; charset=UTF-8
Auto-Submitted: auto-generated
Precedence: bulk
X-Cron-Env: <XDG_SESSION_ID=70>
X-Cron-Env: <XDG_RUNTIME_DIR=/run/user/0>
X-Cron-Env: <LANG=ja_JP.UTF-8>
X-Cron-Env: <MAILTO=sugilog@test.example>
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <HOME=/root>
X-Cron-Env: <PATH=/usr/bin:/bin>
X-Cron-Env: <LOGNAME=root>
X-Cron-Env: <USER=root>

Linux 3.10.0-327.22.2.el7.x86_64 (sugilog)      2016年12月20日  _x86_64_        (4 CPU)

07時37分20秒       LINUX RESTART

07時40分01秒     CPU     %user     %nice   %system   %iowait    %steal     %idle
(以下省略)

その他

ちなみに、-mで渡したスクリプトがイケてなくと何かしら失敗していると、ログにそれっぽい出力がある。

Dec 20 10:47:01 sugilog CROND[5604]: (root) CMD (time /usr/bin/sar -P ALL)
Dec 20 10:47:01 sugilog CROND[5603]: (root) MAIL (mailed 8204 bytes of output but got status 0x0001#012)

あとは

cronから標準入力で渡されるテキストはメール形式なので、メールとしてパースすれば、構造化されたデータとして扱える。

例えばruby

require "rubygems"
require "mail"

text = STDIN.read

message = Mail.new(text)
message.header_fields.each do |field|
  puts "#{field.name} = #{field.value}"
end
puts message.body
From = "(Cron Daemon)" <root>
To = sugilog@test.example
Subject = Cron <root@sugilog> /usr/bin/sar -P ALL
Content-Type = text/plain; charset=UTF-8
Auto-Submitted = auto-generated
Precedence = bulk
X-Cron-Env = <XDG_SESSION_ID=70>
X-Cron-Env = <XDG_RUNTIME_DIR=/run/user/0>
X-Cron-Env = <LANG=ja_JP.UTF-8>
X-Cron-Env = <MAILTO=sugilog@test.example>
X-Cron-Env = <SHELL=/bin/sh>
X-Cron-Env = <HOME=/root>
X-Cron-Env = <PATH=/usr/bin:/bin>
X-Cron-Env = <LOGNAME=root>
X-Cron-Env = <USER=root>
Linux 3.10.0-327.22.2.el7.x86_64 (sugilog)      2016年12月20日  _x86_64_        (4 CPU)

07時37分20秒       LINUX RESTART

07時40分01秒     CPU     %user     %nice   %system   %iowait    %steal     %idle
(以下省略)

参考

qiita.com