Skip to content

Instantly share code, notes, and snippets.

@doitian
Last active September 19, 2025 14:24
Show Gist options
  • Save doitian/34f6c7d0f2fff61459815ae1cdc0bfcc to your computer and use it in GitHub Desktop.
Save doitian/34f6c7d0f2fff61459815ae1cdc0bfcc to your computer and use it in GitHub Desktop.
#!/bin/bash
# Script to delete AWS Glacier archives with retry logic and resume functionality
# Usage: ./delete-glacier-archives.sh [resume_archive_id]
#
# The script reads archive IDs from the provided file and deletes them one by one
# If an archive deletion fails, it prints the error and retries
# The script can resume from a specific archive ID if provided as an argument
set -euo pipefail
# Environment variables required:
# vault - The vault name
# aid - The account ID
vault=
aid=
# Configuration
MAX_RETRIES=3
RETRY_DELAY=5 # seconds
ARCHIVE_FILE="archives.txt"
# Check if required environment variables are set
if [[ -z "${vault:-}" ]]; then
echo "Error: Environment variable 'vault' is not set"
echo "Usage: export vault=your_vault_name"
exit 1
fi
if [[ -z "${aid:-}" ]]; then
echo "Error: Environment variable 'aid' is not set"
echo "Usage: export aid=your_account_id"
exit 1
fi
# Check if archive file exists
if [[ ! -f "$ARCHIVE_FILE" ]]; then
echo "Error: Archive file '$ARCHIVE_FILE' not found"
echo "Please create a file named '$ARCHIVE_FILE' with one archive ID per line"
exit 1
fi
# Function to delete a single archive with retry logic
delete_archive() {
local archive_id="$1"
local attempt=1
while [[ $attempt -le $MAX_RETRIES ]]; do
echo "Attempt $attempt/$MAX_RETRIES: Deleting archive $archive_id"
if aws glacier delete-archive \
--account-id "$aid" \
--vault-name "$vault" \
--archive-id="$archive_id" 2>&1; then
echo "✓ Successfully deleted archive: $archive_id"
return 0
else
echo "✗ Failed to delete archive: $archive_id (attempt $attempt/$MAX_RETRIES)"
if [[ $attempt -lt $MAX_RETRIES ]]; then
echo "Retrying in $RETRY_DELAY seconds..."
sleep $RETRY_DELAY
fi
attempt=$((attempt+1))
fi
done
echo "ERROR: Failed to delete archive after $MAX_RETRIES attempts: $archive_id"
return 1
}
# Function to find the starting line number for resume functionality
find_start_line() {
local resume_id="$1"
local line_num=1
while IFS= read -r archive_id; do
# Skip empty lines and comments
[[ -z "$archive_id" || "$archive_id" =~ ^[[:space:]]*# ]] && { line_num=$((line_num+1)); continue; }
if [[ "$archive_id" == "$resume_id" ]]; then
echo "$line_num"
return 0
fi
line_num=$((line_num+1))
done < "$ARCHIVE_FILE"
echo "Error: Resume archive ID '$resume_id' not found in $ARCHIVE_FILE"
exit 1
}
# Main execution
main() {
local resume_archive_id="${1:-}"
local start_line=1
local total_archives
local processed=0
local successful=0
local failed=0
# Count total archives (excluding empty lines and comments)
total_archives=$(grep -v '^[[:space:]]*$' "$ARCHIVE_FILE" | grep -v '^[[:space:]]*#' | wc -l)
# If resume archive ID is provided, find the starting line
if [[ -n "$resume_archive_id" ]]; then
echo "Resuming from archive ID: $resume_archive_id"
start_line=$(find_start_line "$resume_archive_id")
echo "Starting from line $start_line"
fi
echo "Starting deletion process..."
echo "Vault: $vault"
echo "Account ID: $aid"
echo "Total archives to process: $total_archives"
echo "----------------------------------------"
# Process each archive ID
local line_num=1
while IFS= read -r archive_id; do
# Skip lines before the start line
if [[ $line_num -lt $start_line ]]; then
line_num=$((line_num+1))
processed=$((processed+1))
successful=$((successful+1))
continue
fi
# Skip empty lines and comments
if [[ -z "$archive_id" || "$archive_id" =~ ^[[:space:]]*# ]]; then
line_num=$((line_num+1))
continue
fi
# Trim whitespace
archive_id=$(echo "$archive_id" | xargs)
processed=$((processed+1))
echo "[$processed/$total_archives] Processing archive: $archive_id"
if delete_archive "$archive_id"; then
successful=$((successful+1))
echo "$archive_id" > last_success.txt
else
failed=$((failed+1))
echo "FAILED: $archive_id" >> "failed_archives_$(date +%Y%m%d_%H%M%S).txt"
fi
echo "Progress: $processed/$total_archives (Success: $successful, Failed: $failed)"
echo "----------------------------------------"
line_num=$((line_num+1))
done < "$ARCHIVE_FILE"
echo "Deletion process completed!"
echo "Total processed: $processed"
echo "Successful: $successful"
echo "Failed: $failed"
if [[ $failed -gt 0 ]]; then
echo "Failed archive IDs have been saved to failed_archives_*.txt"
echo "You can retry failed deletions by creating a new archive file with the failed IDs"
exit 1
fi
echo "All archives deleted successfully!"
}
# Show usage information
show_usage() {
echo "Usage: $0 [resume_archive_id]"
echo ""
echo "Environment variables required:"
echo " vault - The vault name"
echo " aid - The account ID"
echo ""
echo "The script reads archive IDs from '$ARCHIVE_FILE'"
echo ""
echo "Examples:"
echo " export vault=my-vault"
echo " export aid=123456789012"
echo " $0"
echo ""
echo " # Resume from specific archive ID:"
echo " $0 kFxTB7FtdCKdVhf9cttU9iSulXIX2HsK2JXpKqK2QdONxaGao9GDIQKIXKCeMKTqNm4Tc6csia5QuxZrLEeM9vKSknmvbtpz6AHhkxCrO3nmHJuM6S1RsMKZTLSuBnP4RPVPcRUaUQ"
}
# Handle help flag
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
show_usage
exit 0
fi
# Run the main function
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment