アンバサダーです。
Mackerel Advent Calendar真っただ中で私の出番は終わりましたが、ネタができたので書きます。


Windowsの日次バッチ、監視したくないですか?
タスクスケジューラから起動してなんか勝手に動いて気がついたら終わってるやつ。
ということで調べてみました。

単体のサーバーのバッチなら、そのサーバーに入って確認すればそれでOKなんですが、複数サーバーでいろんなバッチが走ってると確認するのも一苦労ですよね。
「うちはそのへんちゃんとまとめて確認できるようなダッシュボードあるぜ」って人はそれでいいと思いますが、「作ったほうがいいのはわかるけど、そこまで手が回ってない」みたいなケースではMackerelで監視すれば多少は楽になるのではないかと思います。


前提条件

  • Windowsのタスクスケジューラとかでバッチを走らせている
  • バッチは終了ステータスを適切に返す(正常なら0)
  • Powershellが動かせる
  • インターネットへのOutboundが許可されている
  • Mackerelのサービスとかロールとか作れる
あたりの環境をターゲットとします。
あと、mackerel-agentをインストールしてホストとして登録されているものとして説明します。
今回使用するmkr.exeはWindowsの場合はmackerel-agentのインストーラーに付属しているので、mackerel-agentはインストールしておいてください。

要件

今回の監視に求められる要件を整理します。
  1. バッチ処理本体には手を入れたくない
  2. バッチの処理結果の成否を確認したい
  3. (バッチの処理に失敗したら通知がほしい)
  4. バッチ処理の成否に関わらず、履歴がみたい
あたりでしょうか?

方針

上記の要件を満たすように方針を立てます。
1~3に関しては、 mkr wrapを噛ましてやれば良さそうです。
4が少々問題で、MackerelはOK状態は平常運転なので、チェック監視の履歴は(少なくとも、我々がアクセスできる範囲には)持っていません(サポート確認済み)。
そのため、何らかの方法で履歴を保持する必要があります。Mackerelで任意のデータを投稿するといえば、そう、グラフアノテーションですね?
ということで、履歴はグラフアノテーションに投稿するようにしてみます。

ここまでをまとめると、
  1. バッチを起動するためのタスクスケジューラのコマンドをいじってmkr wrapを噛ませる
  2. mkr wrapを噛ませてやればMackerelに処理結果が投稿される
  3. 処理が失敗すればMackerelがアラートを上げてくれる
  4. mkr annotationsを利用してバッチの処理結果のグラフアノテーションを作成する

実装

参考的に実装したものがこちらです



このうち、「awesome-batch.ps1」はバッチのモックだと思ってください。
本体は「mkr-wrap.ps1」で、ここにもモックに対応させるためのコードが入っています。実際の処理は15行目あたりのfunction定義からです。
簡単に処理の内容を説明します。

  • 15行目からのfunction: グラフアノテーションに投稿するため、エポック秒を計算するfunctionです。
  • 19行目: バッチ処理の開始時間を取得しています。
  • 22行目: バッチ本体のフルパスを組み立てる処理です。awesome-batch.ps1とmkr-wrap.ps1は同一ディレクトリにいる想定で作成しています。プロダクションで利用する場合にはここのパスをどう組み立てるかも考慮する必要がありそうです。
  • 24行目~28行目: バッチ処理をmkr wrap経由で起動しています。グラフアノテーションのdescriptionに設定するためにバッチが標準出力に吐いた内容を拾っています。各オプションについてはMackerelのドキュメントを見て、注意事項や制限事項をよく認識した上で適切なものを指定してください。(特に auto-closeやdetailあたり)
  • 30行目: バッチ処理の終了コードを拾っています。本スクリプト自体の終了コードをバッチの終了コードに合わせるために使用します。
  • 32行目: バッチ処理の終了時間を取得しています。これと19行目の開始時間を利用してグラフアノテーションを作成していきます。
  • 35行目~40行目: グラフアノテーションを作成しています。ここもオプションについては公式のドキュメントを参考にしてください。ここではサービスにグラフアノテーションを作成していますが、今回のようなケースでは、専用のロールを作成してそこに作成するほうがいいと思います。

タスクスケジューラの設定

タスクスケジューラの細かい設定方法等については説明しません。よくわからない場合は、@ITあたりの解説記事を参考にしてください。

ここでは、操作タブのプログラムの指定方法のみ説明します。
タスクスケジューラからは直接ps1スクリプトは指定できないのでPowerShellを起動して実行する必要があります。
そのため、「プログラム/スクリプト」には「powershell」を入力します。
そして、実際に起動するスクリプトはFileオプションを付けて指定します。

01_task_scheduler
あと、自作のps1スクリプトを動かすためにはExecutionPolicyが最低でもRemoteSignedである必要があるため、これも指定します。「俺はPowerShellのExecutionPolicyはちゃんと設定しているぜ」という場合でも、タスクスケジューラ経由で起動されたPowerShellだとExecutionPolicyの設定が反映されていない場合がある(というかされていなかった)ので指定します。
また、これでタスクが実行されるといきなりPowerShellのウィンドウが出てきて、処理途中で誤って終了させたりしても困るのでウィンドウが出てこないようにWindowStyleを指定します。普通に使ってるマシンでバッチを動かすのかという問題はここでは議論しないことにします。

最終的にタスクスケジューラのタスクスケジューラライブラリで操作タブを見た時に以下のようになっていればOKだと思います。
powershell -ExecutionPolicy RemoteSigned -WindowStyle Hidden -File C:\Path\To\wrap.ps1
02_task_scheduler
というか、これをあの小さい入力エリアで指定するのはめんどくさいので、これを書いたバッチファイルを作ってもいいかもしれませんね。

実行結果

このタスクが実行されるとMackerelのサービス画面でグラフアノテーションを確認することができます。
03_annotation
バッチの実行に失敗すると、当然アラートが上がります。
04_alert
今回はバッチが失敗したのでもう一度走らせたようなイメージです。auto-closeを有効にしているので自動でCloseしていますね。

注意点

ここまでの説明ではハマりポイントを避けるようにしていますが、他にもハマりポイントがあるので書いておきます。
  • mkr wrapで投稿した監視項目は一定時間経つとホストのMonitorから消えるようです
  • powershell を WindowStyle=Hiddenで起動するようにしていても、起動時に一瞬だけウィンドウが出てきます
  • バッチの標準出力を拾ってmkr annotations createに渡していますが、変数をダブルクォートで囲んでやらないと標準出力が複数行になった場合にグラフアノテーションでは1行目のみしか投稿されません。上記ソースコードの40行目あたりの話ですね。おそらく実行時に変数展開して改行コードで別コマンド扱いされているのだと思います。今回はdescriptionをコマンドの最後に指定しているので1行目しか投稿されない以外は正常にグラフアノテーションが作成できたので原因の究明に少し時間がかかりました。


ということで、mkrを駆使するとバッチの履歴を確認することができる話でした。いかがでしたでしょうか?

参考

Mackerelは公式のドキュメントが充実してるので公式を見れば全部書いてありますね。