プログラミング

Google Apps Script(GAS)で自宅サーバーの死活監視をする

投稿日:

前置き

自宅サーバー使ってますか?
最近もう流行らないかな、と思ったらRaspberry Piの流行で機器も電気代も安価に組めるようになったりして、地味に持っている人も多いんじゃないかな、と思ってます。

自宅サーバーはいつの間にか死にがちですよね。
死んだら教えてくれよ!って思うんですが、死人には口がないので教えてくれない。
リッチな環境なら複数台で相互監視すればいいですが、複数台も持ってねぇよ、って人。
Google Apps Script(GAS)に監視させる、という手があります。
他にもいろんなクラウドサービスはありますが、GASはGoogleアカウントを持ってればだいたい誰でも使えるので敷居が低いです。

概要

さて監視と言っても、GASに自作サーバーをポーリングさせるのは得策ではありません。自宅サーバーを外部から見える位置に公開しないといけなくなるので。
そうじゃなくて、自宅サーバー側からGASに定期的に信号を送ってやって、信号が途絶えたら死んだ、という方式を取ります。いわゆるハートビートってやつですね。

できあがり

GAS側

GASは”doPost”という関数を作ることで、POSTを受け取るWeb APIを置くことができます。
「公開」から「ウェブアプリケーションとして導入」を選ぶと公開できます。
これは通常認証を必要としますが、どうせURLなんかバレやしないので、認証不要になるよう”Anyone, even anonymous”で公開してやりましょう。

function doPost(e) {
  // POSTデータ確認
  if (e == null || e.postData == null || e.postData.contents == null) {
    Logger.log("POST ERROR");
    return ContentService.createTextOutput("NG").setMimeType(ContentService.MimeType.TEXT);
  }
  // JSONパース
  var requestJSON = e.postData.contents;
  var requestObj = JSON.parse(requestJSON);
  
  // リクエスト解析
  if (requestObj.triggerDateText == null) {
    Logger.log("JSON ERROR");
    return ContentService.createTextOutput("NG").setMimeType(ContentService.MimeType.TEXT);
  }
  
  // トリガーを設定
  var triggerDate = new Date(requestObj.triggerDateText);
  const triggers = ScriptApp.getProjectTriggers();
  for(const trigger of triggers){
    if(trigger.getHandlerFunction() == "checkTimer"){
      ScriptApp.deleteTrigger(trigger);
    }
  }
  ScriptApp.newTrigger('sendAlertMail').timeBased().at(triggerDate).create();
  
  return ContentService.createTextOutput("OK").setMimeType(ContentService.MimeType.TEXT);
}


function sendAlertMail() {
  // アラートメール送信
  GmailApp.sendEmail('myAddress@gmail.com', 'サーバ死んだよ');
}

自宅サーバー側

Linuxを想定してシェルコマンドです。好きな言語で書いてください。
URLは自分のGASで公開したAPIのものに書き換えて。
このコマンドをcronなどで5分おきに実行し続けます。10分間止まるとトリガーが発動してメールが飛びます。

$ curl -L -X POST -d "{\"triggerDateText\":$(date "+%s000" -d "10 minutes")}" -sS "https://script.google.com/macros/s/AKfycbXxxxxxxxxxxxxxxxxxxx/exec"

解説

ほぼ書いてある通りです。
GASはスクリプトを定期実行するためにトリガーという仕組みがあるんですが、これは任意の日時を指定して発動できます。
また、スクリプト自身からトリガーを設定できます。
そのため、「POSTを受け取ってトリガーを再設定するスクリプト」を作ることで、「この時刻までに次の信号が来なかったらメールを出す」という機能を実現できます。
処理の流れは以下のような感じ。

  1. クライアントがn分おきに”メールを出す時刻”をGASにPOSTし続ける
  2. GASはクライアントから時刻を受け取って(doPost関数)、既存のトリガーを消して新しいトリガーに更新し続ける。
  3. クライアントからの通信が途絶えるとトリガーが発動して、自分のメールアドレス向けにアラートが飛ぶ(sendAlertMail関数)

送信する側もAPIにPOSTさえ出来れば良いのでcurlコマンドで十分ですし、任意の言語で書けば良いです。ただ、リダイレクトを適切に処理する必要があるので気をつけてください。
また、GAS側はNGだのOKだのを返すように見えますが、どうも上手く動かないようなので気をつけて。

蛇足1 ログを取る

スクリプト的には以上ですが、もっと色々ログを取りたいならスプレッドシートと組み合わせるという手があります。
そもそもスプレッドシート上のスクリプトにしてしまうことができますし、上のコードもJSONでやりとりするように書いているので、JSONに情報を増やせば好きなものを記録できます。

蛇足2 サーバーをタイマ起動させて監視

実は自分は上記の使い方をしてません。
録画鯖を番組開始前にタイマ起動するように仕込んでいて、タイマ起動に失敗したらアラートを上げるようにしています。常時起動させると電気代がアレなので。
このタイマ起動にはLinuxのwakealermというのを使っていて、/sys/class/rtc/rtc0/wakealarmにUNIXTIMEを入れてシャットダウンすれば自動で上がってきます。
GASのトリガーは「起動時間の10分後」に設定していて、10分経って上がってこなかったらアラートが上がるようにしています。
色々使いみちがあるよ、という話でした。

-プログラミング

執筆者:


comment

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

関連記事

no image

UnityのCompute Shaderに線分と三角形の衝突判定をさせる

はじめてCompute Shader使ってみた。でもあまり性能は出ないのでただの失敗の記録です。 まず元のアルゴリズムはコレ。 線分と三角形の当たり判定 – 富士見研究所 で、これをまず三角形の表裏問 …

YouTube Data APIをGoogle Apps Script(GAS)から使おう

YouTubeってAPIから色々な情報を取ることができるんですよ。 APIの情報はリファレンスにまとまってるんですが、APIキーだのOAuth2.0だの、使い始めるまでがまぁまぁ面倒なんですね。 で、 …

GeoJSONで市町村境界をマージして都道府県境界にしたい(その1)

前回の続きで、国土地理院の「国土数値情報」っていうオープンデータで遊んでいます。独立した記事なので前回のは読まなくても良いです。 やりたいこと 国土数値情報で提供されている「行政区域データ」は、市町村 …

どうして私はC言語で仕事をしているのか

みなさんプログラミング言語は学んでますか?今から始めますか? 最初に学ぶべきプログラミング言語ってなんだと思いますか?そうです。C言語です。 C#でもC++でもObjective-Cでもなく、Pure …

no image

[python]Windows環境でsubprocessするときは文字コードに気をつけて

pythonは内部の文字コードと実行環境の文字コードが色々絡み合っていて、いろんなところで悪さをする。 特にWindows環境だと、内部はUTF-8で動いているのに実行環境はShift-JIS(正確に …