Slackは色々hackできるから楽しい。
Python3で、WEBサイトのステータスを自動かつ定期的にチェックして、200(正常)以外ならその結果をSlackに流す、という死活監視Botを作ってみた。その備忘録です。
自動で実行したいので、Python3のソースコードをAWSのLambdaに置き、CloudWatchのcronで二時間に一度、定期実行するようにする。
こんな人向けの記事
すでにAWSとSlackアカウントを持っていて、かつPythonの開発環境がすでに構築されている人が対象です。僕自身はWeb Analystなのでピュアなエンジニアではないけれど、そんな人でもSlackを便利にできるよというTipsのつもり。
(1)SlackのWebhook URLを取得する
まずSlackに自動投稿するための設定をする。
SlackのApps管理画面にアクセスする(SlackのAPI管理画面って導線が結構分かりづらい)。
「Create New App」をクリック
作成するApp Nameは何でもOK。「Development Slack Workspace」ではBotをPostするWorkspaceを選ぶ
Incoming Webhooksの設定画面に進んで「ON」にすると「Add New Webhook to Workspace」ボタンが出るので次に進む
BotがPostするチャンネルを選んで「Allow」
Allowすると先ほどのページに戻ってくるので、生成されたWebhook URLをcopyする(後ほど書くPythonコードで使う)
(2)Pythonコードの準備
Python3でコード書きます。
# -*- coding: utf-8 -*-
import requests
import json
urls = ['https://www.example.com']
def post_slack_h(c):
post_url = 'SLACK_WEB_HOOK_URL'
requests.post(post_url, data = json.dumps({
'text': c,
}))
targets = []
def status_check(a="",b=""):
content = "*Alive monitoring*" "\n\n"
for url in urls:
try:
s = requests.get(url, timeout=10).status_code
except requests.exceptions.ReadTimeout:
content = url " Time out(10s)" "\n"
targets.append(url)
except requests.exceptions.ConnectionError:
content = url " Connection error" "\n"
targets.append(url)
else:
if s == 200:
content = url " " str(s) "\n"
else:
content = url " " str(s) "\n"
targets.append(url)
content = "\n\nThis notification is sent only if the result involves the off-normal status. This bot is scheduled every two hour.\n"
if not targets:
pass
else:
post_slack_h(content)
9行目のSLACK_WEB_HOOK_URL
には先ほど生成したURLを使う。
20行目ではタイムアウトを10秒に指定している。
status_check関数に適当な引数を設定している理由は、AWS Lambda実行の際に引数がないとエラーになったから(確か)。
どの関数を実行するかはAWS Lambda上で指定するので、ソース自体はシンプルな形にしておく。
(3)Pythonコードのzipファイルを準備(AWS Lambdaへのアップロード用)
AWS Lambda上でPythonを直接書いて動かしたりするだけなら簡単だけど、外部パッケージもimportするには一手間必要。
上記のソースではrequests
とjson
というパッケージをimportしているが、requests
は外部パッケージなので、インストールしてソースと一緒にzipファイルにまとめる必要がある(jsonは標準ライブラリ)。
ちなみにパッケージインストーラーはpip(なのでpipが動く環境という前提でおなしゃす)。
$ cd /{pythonコードを実行するディレクトリ}
$ pip install requests -t ./
$ zip -r py_health_check ./*
これでPythonコードや外部パッケージを内包した「py_health_check.zip」というzipファイルが同じディレクトリに出来上がっているはず。
(4)AWS Lambdaにアップロード
AWS管理画面を開いて、Lambdaに移動
新しく関数を作成
関数作成画面では、
「一から作成」を選択、
「関数名」は何でもOK、
「ランタイム」は「Python3.6」を選択
作成された関数の編集画面に遷移するので、
「コードエントリタイプ」から「.zipファイルをアップロード」を選択して先ほどのzipをアップロード(成功すると下のフォームにソースコードが展開される)、
「ランタイム」が「Python 3.6」であることを確認、
「ハンドラ」は「{ファイル名}.{実行する関数名}」というフォーマットなのでhealthcheck.status_checkにする
(5)テスト
正しく動くかテストする。
ちなみに今回初めて知ったんだけど、example.comはステータスコード200を返すみたいなのでチェックするURLは適当にhttps://www.exampleddddddddddddddddd.com
みたいなのにしましょう。
Lambda右上の「テスト」をクリック
「イベント名」は適当でいいのでそのままテストを「作成」し、もう一度右上の「テスト」をクリック
すると、実行ログが出力されます。グリーンは成功やね
さてSlackのチャンネルを見てみよう。
無事投稿されておりました。
ちなみに上述のPythonコードでは、試したWEBサイトのURLが200を返してしまう(=正常)とSlackには何もPostされない。テスト時に注意。
(6)AWSのCloudWatchを使ってCron処理化
やっと!終わりに近い!(スクショ撮るの大変だった。世のブロガーすごい)
「あるURLのステータスをチェックして200以外ならSlackにアラートをPostする」という処理自体は完成したので、あとはこれを定期処理化する。
AWSの関数編集画面で「トリガーを追加」
「トリガー」ではCloudwatch Eventを選択
「ルール」は新規ルールの作成
「ルール名」は適当に。「」スペースは使えないので「every_2_hour」とか無難
「ルールタイプ」は「スケジュール式」で、式はcron(0 0/2 * * ? *)
と記述
完了!
下のような表示になったらOK。これで二時間に一度、死活監視Botが仕事をしてくれるはず。おつかれさまー。
おまけ
Lambdaはソースコードのzipファイルをアップロードし直すのが中々しんどいので、Webhook URLやWEBサイトURLなどはLambda環境変数を使ってAWS管理画面から編集できるようにしておくといいと思う。
また、Slackに投稿するアプリ名やアイコン画像はSlackのAppsページのBasic Informationから変えられる。