SQS: drain a queue to local JSONL
Pop messages off an SQS queue, write each Body to disk for inspection. The first move when something's wedged in a queue.
Setup
- → brew install awscli
- → aws configure (or AWS_PROFILE / AWS_ACCESS_KEY_ID env vars)
Cost per run
free
The one-liner
$ Q="https://sqs.eu-west-1.amazonaws.com/123456789012/my-queue"
while MSGS=$(aws sqs receive-message --queue-url "$Q" \
--max-number-of-messages 10 --wait-time-seconds 5) \
&& echo "$MSGS" | jq -e '.Messages | length > 0' >/dev/null; do
echo "$MSGS" | jq -c '.Messages[]?.Body | fromjson? // .' >> /tmp/drained.jsonl
echo "$MSGS" | jq -r '.Messages[]?.ReceiptHandle' \
| xargs -I {} aws sqs delete-message --queue-url "$Q" --receipt-handle {}
done
wc -l /tmp/drained.jsonlWhat each stage does
- [01] aws
aws sqs receive-message --queue-url "$Q" --max-number-of-messages 10 --wait-time…Long-poll for up to 10 messages, waiting up to 5s. Returns {Messages: [{Body, ReceiptHandle, ...}]} or {} when empty. - [02] jq
jq -e '.Messages | length > 0'Exit-code test: jq -e returns non-zero if the result is null/false/empty — so the while-loop terminates cleanly when the queue's empty. - [03] jq
jq -c '.Messages[]?.Body | fromjson? // .'For each message: try fromjson (most queue payloads are JSON-encoded strings); fall back to raw text if not. -c keeps each on a single line for JSONL. - [04] aws
xargs -I {} aws sqs delete-message --queue-url "$Q" --receipt-handle {}Receive-message doesn't auto-delete — you must explicitly delete each message by ReceiptHandle, or it'll reappear after the visibility timeout.
Expected output (sample)
{"order_id":"42","status":"failed","attempts":3}
{"order_id":"43","status":"failed","attempts":2}
... 47 more lines
49 /tmp/drained.jsonlCaveats & tips
- This DESTRUCTIVELY drains the queue — messages are deleted. To peek without deleting, remove the delete-message line.
- Visibility timeout matters: if your delete is slow, messages reappear. Default is 30s; raise on the queue if you do slow work per message.