1
0

AWS SQS デッドレターキューのメッセージを一括削除

Posted at

デッドレターキューのメッセージを全削除するシェルスクリプトを作ってみた。

デッドレターキューに限ったことではないのですが、やりたかったこととしては、デッドレターキューにあるメッセージを全削除することだったので、このタイトルです。
(通常のキューのメッセージを全削除することはそうそうないかなと思って)

やりたかったこと(背景)

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) を利用した方がシンプルです。

あとがき(言い訳)

もう少し省略した書き方ができますが、自分がシェルスクリプト初心者なんで、初心者にとってわかりやすいかなという気持ちで敢えて冗長な書き方もしています。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0