概要
EC2のcrontab
-> Pythonスクリプト実行 -> RDSのストプロ -> Slackへ通知、という流れを構築しました。
具体的には、
「毎日9時に、プロシージャで実施した結果を、指定のSlackチャンネルに通知する」
という流れがゴールです。
今回は、AWSのEC2サーバでクーロンを利用してPythonスクリプトを定期的に実行させる方法になります。Pythonスクリプトの実行はRDSのストプロを呼び出し、SQL結果を特定のSlackチャンネルに通知します。
構築手順と注意点を解説します。
手順
まず、EC2サーバに今回のツール用のディレクトリを作成します。
ここでは、とあるDBテーブルからレコード数をカウントするツールを例にしますので、ディレクトリ名はcount-number-tool
とします。
その下に、以下の3つを作成していきます。
count-number-tool
├── venv
├── number-counter.py
└── run_script.sh
venv
の作成
まずは仮想環境を作成します。
サーバ全体に影響を与えずにパッケージをインストールしたいためです。
(個別にインストールするライブラリがない場合は不要です)
以下のコマンドで仮想環境を作成しましょう。
python3 -m venv venv
※もし、まだpythonがインストールされていない場合は以下のコマンドでインストールしましょう
sudo yum install -y python3
仮想環境を作成したらアクティベートします。
source venv/bin/activate
利用したいライブラリをインストールしましょう。
例えば、以下のような感じです。
pip install pymysql
pip install requests
run_script.sh
の作成
run_script.sh
は、クーロンで呼び出すスクリプトです。
以下のように、仮想環境の起動&Pythonスクリプトの実行、を記載します。
#!/bin/bash
source /home/ec2-user/count-number-tool/venv/bin/activate
python /home/ec2-user/count-number-tool/number-counter.py
deactivate
シェルスクリプトには実行権限を与えておきます。
chmod +x /home/ec2-user/count-number-tool/run_script.sh
number-counter.py
の作成
実行したいPythonスクリプトを書きます。
今回は、count_number
というプロシージャを実行して、その結果をSlackに通知するコードにしています。
import json
import os
from datetime import datetime, timedelta
import pymysql
import requests
import logging
from decimal import Decimal
logger = logging.getLogger()
logger.setLevel(logging.INFO)
rds_host = 'xxx'
rds_user = 'xxx'
rds_password = 'xxx'
rds_db = 'xxx'
slack_webhook_url = 'https://hooks.slack.com/services/xxx'
def send_slack_notification(webhook_url, message):
payload = {
"text": message
}
response = requests.post(webhook_url, data=json.dumps(payload), headers={'Content-Type': 'application/json'})
if response.status_code != 200:
raise ValueError('Request to Slack returned an error {}, the response is:\n{}'.format(response.status_code, response.text))
def decimal_default(obj):
if isinstance(obj, Decimal):
return float(obj)
raise TypeError
def main():
logger.info("Script started")
today = datetime.now()
yesterday = today - timedelta(1)
report_date = yesterday.strftime('%Y-%m-%d')
logger.info("Report date: {}".format(report_date))
try:
connection = pymysql.connect(host=rds_host, user=rds_user, password=rds_password, db=rds_db)
logger.info("Connected to RDS")
except Exception as e:
logger.error("Error connecting to RDS: {}".format(e))
raise
try:
with connection.cursor() as cursor:
cursor.callproc('count_number', [report_date])
result = cursor.fetchall()
logger.info("Stored procedure result: {}".format(result))
if result:
row = result[0]
message = "Report for {}:\n".format(report_date)
message += "hoge, foo, example, sample, test\n"
message += "{},{},{},{},{},{}\n".format(row[0], row[1], row[2], row[3], row[4])
send_slack_notification(slack_webhook_url, message)
logger.info("Slack notification sent"
finally:
connection.close()
logger.info("RDS connection closed")
return {
'statusCode': 200,
'body': json.dumps(result, default=decimal_default)
}
if __name__ == "__main__":
main()
※EC2サーバはRDSへアクセスできる状態である必要があります。セキュリティグループで許容していることを確認してください
RDSのストプロ例
以下は、sample_tableのcreate_dateカラムが前日のもので、かつ、sample_noカラムに指定の文字列から始まるレコードが何件あるか、というSQLになります。上述のPythonスクリプトで以下のプロシージャを実行します。
CREATE DEFINER=`root`@`%` PROCEDURE `sample`.`count_number`(IN report_date DATE)
BEGIN
SELECT
SUM(CASE WHEN sample_no LIKE 'hoge%' THEN 1 ELSE 0 END) AS count_hoge,
SUM(CASE WHEN sample_no LIKE 'foo%' THEN 1 ELSE 0 END) AS count_foo,
SUM(CASE WHEN sample_no LIKE 'example%' THEN 1 ELSE 0 END) AS count_example,
SUM(CASE WHEN sample_no LIKE 'sample%' THEN 1 ELSE 0 END) AS count_sample,
SUM(CASE WHEN sample_no LIKE 'test%' THEN 1 ELSE 0 END) AS count_test
FROM mysql57.sample_table
WHERE create_date BETWEEN CONCAT(report_date, ' 00:00:00') AND CONCAT(report_date, ' 23:59:59');
END
crontabの設定
EC2サーバで以下を実行し、Cronジョブを設定します。
crontab -e
crontab コマンドは、cron ジョブの実行のほか、編集、リスト、除去を行います。 cron ジョブとは、cron デーモンによりスケジュールされ、一定の周期で実行されるジョブです。 cron ジョブの実行を要求するには、crontab コマンドに -e フラグを指定します。 crontab コマンドは、編集セッションを起動します。この編集セッションで、crontab ファイルを作成できます。
https://www.ibm.com/docs/ja/aix/7.2?topic=c-crontab-command
ジョブは以下のように追加します。
00 9 * * * /home/ec2-user/count-number-tool/run_script.sh
上記は、毎朝9時に、run_script.sh
を実行する、というもの。
これにより、Pythonスクリプトが定期的に実行され、Slackへ毎朝結果が届くようになりました。
参考
AWS Lambdaを利用して構築する手順も以前に記事にしました。ご参考までに。