Last active
September 19, 2025 14:24
-
-
Save doitian/34f6c7d0f2fff61459815ae1cdc0bfcc to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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