デッドレターキューのメッセージを全削除するシェルスクリプトを作ってみた。
デッドレターキューに限ったことではないのですが、やりたかったこととしては、デッドレターキューにあるメッセージを全削除することだったので、このタイトルです。
(通常のキューのメッセージを全削除することはそうそうないかなと思って)
やりたかったこと(背景)
SQSを使ったアプリケーションの開発中に、テストで登録したSQSのメッセージがデッドレターキューに溜まってしまった場合に、まとめて消してしまいたい時がある。
AWSマネジメントコンソールで手動でポチポチ削除していたのだが、数が多いとそれなりに面倒。
メッセージの中身をデバッグ用などに取っておきたい場合もあるので、削除する前にJSONファイルに出力しておきたい。
どのファイルに所望のメッセージが格納されているかわかるように、識別可能なキー項目をメッセージから取得してファイル名に付与しておきたい。
AWS CLI を使って一括で削除
Python で boto3 も良いかと思ったが、先ずは、AWS CLI だけで作ってみる。
動作確認環境
$ bash --version
GNU bash, version 5.2.15(1)-release (x86_64-pc-msys)
$ aws --version
aws-cli/2.5.2 Python/3.9.11 Windows/10 exe/AMD64 prompt/off
免責事項
- スクリプトの実行は自己責任でお願いします。本スクリプトを実行することにより生じるいかなる問題に関しましても、筆者は一切責任を負いません。
#!/bin/bash
#
# 指定のデッドレターキュー内の全メッセージを削除
#
# 処理内容
# キュー内のメッセージを取得し、メッセージ内容のキー項目などをファイル名に付与してJSONファイルにメッセージ内容を出力し、メッセージを削除する
#
# 前提条件
# jq が実行できること(PATHが通っていること)
#
set -e
# キュー名
QUEUE_NAME="デッドレターキューの名前"
# キューメッセージ内容JSONファイル出力先ディレクトリ
OUTPUT_DIR="dead_queue"
mkdir -p ${OUTPUT_DIR}
# キュー名でキューのURLを取得(AWSアカウントとリージョン固定なら、わざわざ取得せず、URLを直書きしても良いと思います)
QUEUE_URL=$(aws sqs list-queues --queue-name-prefix ${QUEUE_NAME} --query "QueueUrls[0]" --output text)
# QUEUE_URL="https://sqs.{リージョン}.amazonaws.com/{AWSアカウントID}/${QUEUE_NAME}"
echo "[DEBUG] QUEUE_URL=${QUEUE_URL}" >&2
del_cnt=0
while true
do
message_json=$(aws sqs receive-message --queue-url "${QUEUE_URL}")
if [[ -z "${message_json}" ]]; then
# メッセージを取得できなければ終了
break
fi
# メッセージ削除用に、 ReceiptHandle を取得
receipt_handle=$(echo "${message_json}" | jq -r '.Messages[].ReceiptHandle')
# メッセージ内容を取得
msg_body_json=$(echo "${message_json}" | jq -r '.Messages[].Body')
# メッセージの中のキー項目の値をファイル名に使用する(下記の例では、id )
file_base_name=$(echo "${msg_body_json}" | jq -r '.id')
# メッセージ内容をJSONファイルへ出力
echo "${msg_body_json}" | jq '.' > ${OUTPUT_DIR}/${file_base_name}.json
# メッセージ削除
aws sqs delete-message --queue-url "${QUEUE_URL}" --receipt-handle "${receipt_handle}"
del_cnt=$((++del_cnt))
sleep 1
done
echo "${del_cnt}件のメッセージを削除しました。"
ちなみに、 Messages
配列内の要素は一つであることが前提で記載しています。
なお、AWS CLI で使える JMESPath ではなく、jq を使っているのは好みの問題というのもありますが、削除する前にメッセージ内容をJSONファイルに出力するために、ReceiptHandle
を取得してから、Body
を取得しているので、jq を使っています。
単に、ReceiptHandle
を取得して削除するだけなら、--query オプション(JMESPath) を利用した方がシンプルです。
あとがき(言い訳)
もう少し省略した書き方ができますが、自分がシェルスクリプト初心者なんで、初心者にとってわかりやすいかなという気持ちで敢えて冗長な書き方もしています。