cronの失敗をGoogle Apps Scriptで通知する

はじめに

cronが面倒くさい。特に失敗を通知するのが。

そもそも標準エラー出力があった時だけ通知されるようにするのも面倒なんですが、
AWSを使ってると迷惑メール扱いされないようにAmazon SES使うなり、DNS逆引き設定するなりしないといけないわけです。
こんなのサーバ毎にやってられんわけです。

ということで、そんな面倒なcronの失敗通知をGoogle Apps Scriptを使うことで楽にします。

スプレッドシート

まずは以下のようなスプレッドシートを作ります。

f:id:inocop:20190218175417p:plain

Google Apps Script

スプレッドシートの [ ツール ] > [ スクリプトエディタ ] を開き、以下の関数を登録します。

function doPost(e) {
  var sheet = SpreadsheetApp.getActive().getSheetByName('メーリングリスト');
  var to_emails = sheet.getRange(1, 1, sheet.getLastRow()).getValues();

  var subject = 'エラー通知';
  var body = "以下の処理でエラーが発生しました。\n\n";
  body += "タスク名: " + e.parameter.task_name;
   
  GmailApp.sendEmail(to_emails.join(','), subject, body);
}


続いて、作成した関数を公開します。

スクリプトエディタの [ 公開 ] > [ ウェブアプリケーションとして導入... ] を選択します。
GASを初めて公開する場合、Googleの認証が出るので許可してください。

公開の設定は以下になります。

f:id:inocop:20190218182428p:plain

ここで表示される「現在のウェブアプリケーションのURL」にリクエストを送ることでメールが送信されるようになります。

スクリプトを更新する場合
再度、 [ 公開 ] > [ ウェブアプリケーションとして導入... ] が必要になります。
この時にプロジェクトバージョンを上げないと反映されないので注意してください。

自分も毎回やり忘れます。

cron

cronの処理は何でもいいんですが、
例としてLet's Encriptの更新処理をcronに登録します。

/etc/crontab

# エラーはGASで通知するので、全ての出力をリダイレクト
0  6  *  *  mon root /opt/cron/certbot_renew.sh >> /var/log/certbot_renew.log 2>&1

certbot_renew .sh

#!/usr/bin/env bash

/opt/certbot/certbot-auto renew --no-self-upgrade --deploy-hook "systemctl restart nginx"

# 証明書の更新に失敗したらGAS経由でメール通知
if [ $? != 0 ]; then
  TASK_NAME="certbot_renew.sh"
  curl -X POST -d task_name=$TASK_NAME https://script.google.com/macros/s/${APP_ID}/exec
fi

最後に

メールにこだわらなくていいなら、Slackとかに通知した方が楽。


以上、現場からでした。