En gran parte inspirado por las publicaciones del blog y la esencia ya vinculadas en las otras respuestas, aquí está mi opinión sobre el problema.
Utilicé algunas funciones complicadas de JMESpath para obtener una lista de instantáneas y no es necesario tr.
Descargo de responsabilidad : use bajo su propio riesgo , hice todo lo posible para evitar cualquier problema y mantener los valores predeterminados, pero no me responsabilizaré si le causa problemas.
#!/bin/sh
# remove x if you don't want to see the commands
set -ex
# Some variable initialisation with sane defaults
DRUN='--dry-run'
DO_DELETE=${1:-'no'}
REGION=${2:-'eu-west-1'}
ACCOUNTID=${3:-'self'}
# Get two temporary files
SNAP_FILE=$(mktemp)
IMAGE_FILE=$(mktemp)
# Get the snapshot list and the volume list
aws --region "$REGION" ec2 describe-snapshots --owner-ids "$ACCOUNTID" --query 'Snapshots[*].[SnapshotId]' --output text > "$SNAP_FILE"
aws --region "$REGION" ec2 describe-images --owners "$ACCOUNTID" --filters Name=state,Values=available --query 'Images[*].BlockDeviceMappings[*].Ebs.[SnapshotId]' --output text > "$IMAGE_FILE"
# Check if the outputed command should be dry-run (default) or not
if [ "$DO_DELETE" = "IAMSURE" ]
then
DRUN=''
fi
# count each snapshot id, decrease when a volume reference it, print delete command for those with no volumes
awk -v REGION="$REGION" -v DRUN="$DRUN" '
FNR==NR { snap[$1]++; next } # increment snapshots and get to next line in file immediately
{ snap[$1]-- } # we changed file, decrease the snap counter when a volume reference it
END {
for (s in snap) { # loop over the snapshots
if (snap[s] > 0) { # if we did not decrese under 1 that means there is no volume referencing this snapshot
cmd="aws --region " REGION " " DRUN " ec2 delete-snapshot --snapshot-id " s
print(cmd)
}
}
}
' "$SNAP_FILE" "$IMAGE_FILE"
# Clean up the temp files
rm "$SNAP_FILE" "$IMAGE_FILE"
Espero que el script en sí sea lo suficientemente comentado.
El uso predeterminado (sin parámetros) enumerará los comandos de eliminación de instantáneas huérfanas para la cuenta corriente y la región eu-west-1, extraiga:
aws --region eu-west-1 --dry-run ec2 delete-snapshot --snapshot-id snap-81e5856a
aws --region eu-west-1 --dry-run ec2 delete-snapshot --snapshot-id snap-95c68c7e
aws --region eu-west-1 --dry-run ec2 delete-snapshot --snapshot-id snap-a3bf50bd
Puede redirigir este resultado a un archivo para su revisión antes de buscarlo para ejecutar todos los comandos.
Si desea que el script ejecute el comando en lugar de imprimirlo, reemplácelo print(cmd)por system(cmd).
El uso es el siguiente con un script llamado snap_cleaner:
para comandos de ejecución en seco en la región us-west-1
./snap_cleaner no us-west-1
para comandos utilizables en eu-central-1
./snap_cleaner IAMSURE eu-central-1
Se puede usar un tercer parámetro para acceder a otra cuenta (prefiero cambiar el rol a otra cuenta antes).
Versión simplificada de la secuencia de comandos con la secuencia de comandos awk como línea:
#!/bin/sh
set -ex
# Some variable initialisation with sane defaults
DRUN='--dry-run'
DO_DELETE=${1:-'no'}
REGION=${2:-'eu-west-1'}
ACCOUNTID=${3:-'self'}
# Get two temporary files
SNAP_FILE=$(mktemp)
IMAGE_FILE=$(mktemp)
# Get the snapshot list and the volume list
aws --region "$REGION" ec2 describe-snapshots --owner-ids "$ACCOUNTID" --query 'Snapshots[*].[SnapshotId]' --output text > "$SNAP_FILE"
aws --region "$REGION" ec2 describe-images --owners "$ACCOUNTID" --filters Name=state,Values=available --query 'Images[*].BlockDeviceMappings[*].Ebs.[SnapshotId]' --output text > "$IMAGE_FILE"
# Check if the outputed command should be dry-run (default) or not
if [ "$DO_DELETE" = "IAMSURE" ]
then
DRUN=''
fi
# count each snapshot id, decrease when a volume reference it, print delete command for those with no volumes
awk -v REGION="$REGION" -v DRUN="$DRUN" 'FNR==NR { snap[$1]++; next } { snap[$1]-- } END { for (s in snap) { if (snap[s] > 0) { cmd="aws --region " REGION " " DRUN " ec2 delete-snapshot --snapshot-id " s; print(cmd) } } }' "$SNAP_FILE" "$IMAGE_FILE"
# Clean up the temp files
rm "$SNAP_FILE" "$IMAGE_FILE"