ShellScriptが得意な人もそうでない人もこんにちは。実務でAWSとShellScript(bash)を使っている者です。
学習のために簡単なものを作ってみました。
目的
- ShellScript(bash), AWS, EC2の手を動かした学習
- 個人的にメールだと見落とすことが多いので、勉強会の情報を通知してほしい
- 一番簡単そう、かつ、今業務で使っているのでslackで通知を送ってみる。
処理の概要
- connpassで当日参加予定の勉強会のリマインダーをslackでwebhookを使って通知する
- EC2上でShellScript(bash)動かす
- crontabで毎日10時にキック
- crontabで毎日10時にキック
環境
Amazon Linux AMI release 2018.03
GNU bash, バージョン 4.2.46(2)-release (x86_64-redhat-linux-gnu)
ソース
#!/bin/bashset-eu# 定数readonly CURRENT_DATE=$(date +%Y%m%d)readonly WORKDIR=/$HOME/bot-scheduled-event-info
readonly LOGFILE=${WORKDIR}/log/event_notice_send${CURRENT_DATE}.log
# ログ用exec 2> ${LOGFILE}# tempファイルtmp_api_res=$(mktemp /tmp/tmp_api_res-XXXXXX)trap'rm -rf /tmp/tmp_*' EXIT
# EC2のタグを取得readonly EC2_INSTANCE_NAME="bot-scheduled-event-info"readonly RESOURCE_ID=$(aws ec2 describe-tags --filtersName=value,Values=${EC2_INSTANCE_NAME}--output text | awk'{print $3}')readonly EC2_TAGS=$(aws ec2 describe-tags --filtersName=resource-id,Values=${RESOURCE_ID}--output text)readonly WEBHOOK_URL=$(echo"${EC2_TAGS}" | awk'$2=="WEBHOOK_URL"{print $5}')readonly CONNPASS_API_NICKNAME=$(echo"${EC2_TAGS}" | awk'$2=="CONNPASS_API_NICKNAME"{print $5}')readonly SEND_CHANNEL=$(echo"${EC2_TAGS}" | awk'$2=="SEND_CHANNEL"{print $5}')# EC2のタグを元にconnpassのAPIにアクセス
curl -sX GET https://connpass.com/api/v1/event/?nickname=${CONNPASS_API_NICKNAME}\&ymd=${CURRENT_DATE} | jq .>${tmp_api_res}echo========connpassAPIレスポンス==============>>${LOGFILE}cat${tmp_api_res}>>${LOGFILE}echo-e"\n\n\n">>${LOGFILE}readonly results_returned=$(cat${tmp_api_res} | jq .results_returned)# 取得したイベントの件数の分だけslackに通知を送信for((i=0;i<results_returned;i++));do
title=$(jq -r .events[${i}].title ${tmp_api_res})event_url=$(jq -r .events[${i}].event_url ${tmp_api_res})started_at=$(jq -r .events[${i}].started_at ${tmp_api_res} | awk'{print substr($1,12,5)}')ended_at=$(jq -r .events[${i}].ended_at ${tmp_api_res} | awk'{print substr($1,12,5)}')place=$(jq -r .events[${i}].place ${tmp_api_res})address=$(jq -r .events[${i}].address ${tmp_api_res})data=$(cat<<EOF
payload={
"channel": "${SEND_CHANNEL}",
"username": "【リマインダー】本日参加予定の勉強会",
"icon_emoji": ":pencil2:",
"attachments": [{
"pretext": "<!channel> ${started_at}〜${ended_at}",
"title": "${title}",
"text": "${address}${place}\n${event_url}"
}]
}
EOF
)echo===============slack送信==================>>${LOGFILE}echo"${data}">>${LOGFILE}
curl -sX POST --data-urlencode"${data}"${WEBHOOK_URL}>>${LOGFILE}echo-e"\n\n\n">>${LOGFILE}done
0 10 *** /home/ec2-user/bot-scheduled-event-info/sh/event_notice_send.sh
https://github.com/talasago/bot-scheduled-event-info
実行後のイメージ
解説
EC2のタグ
環境変数を取り扱う様に、ソース上には書きたくないけど必要な情報をEC2のタグに設定しました。以下の通りです。- connpassユーザーID
- slackに通知するchannel名
- slack webhook URL
jq -r
for文内の変数にはjsonで設定された””を外します。payloadデータ作成時に、””重複して文字列の開始終了位置が不正にならない様にするためです。
※jq -r
の例は以下のURLもご参照ください。
https://qiita.com/takeshinoda@github/items/2dec7a72930ec1f658af#ダブルクォートが邪魔
気になっている点
EC2のタグの取得
- インスタンス名をキーにResourceIdを取得、そしてResourceIdをキーにconnpassユーザーIDといった本来必要な値を取得しており、分かりづらい。
- EC2のタグは”ソース上には書きたくないけど必要な情報”を書く場所で良いのか。
connpassAPIクエリパラメータ不正時
- nicknameやymdが間違っている時に、connpassに新しく登録された勉強会情報?が返却される。shell上でconnpassのAPIのエラーかどうか判断できていない。
苦労した点や感想など
パイプ処理あまり使ってないので、shell感(?)が足りずに普通のプログラム言語で書いたみたいになっているのが少し悔しいですね。変数とかfor文使わない方法が筆者にはわからないので、より良い案があれば教えてください。
参考にさせていただいた情報
https://uguisu.skr.jp/Windows/crontab.html
http://vdeep.net/shellscript-slack
https://swfz.hatenablog.com/entry/2015/11/18/000152
https://haruka-note.hateblo.jp/entry/20190626_slackfromrsync