Skip to content

Instantly share code, notes, and snippets.

@agners
Last active November 30, 2023 21:18
Show Gist options
  • Select an option

  • Save agners/c5ae781c828dbf76c4cc1e4588c034a5 to your computer and use it in GitHub Desktop.

Select an option

Save agners/c5ae781c828dbf76c4cc1e4588c034a5 to your computer and use it in GitHub Desktop.

Revisions

  1. agners revised this gist Nov 30, 2023. 1 changed file with 6 additions and 0 deletions.
    6 changes: 6 additions & 0 deletions prune-corrupted-layer-metadata.sh
    Original file line number Diff line number Diff line change
    @@ -27,6 +27,12 @@ fi
    # Find unique cache IDs
    cache_ids=$(find "$overlay2_dir" -type f -size 0 \( -name lower -o -name link \) -exec sh -c 'basename $(dirname {})' \; | sort -u)

    # Check if cache IDs are found
    if [ -z "$cache_ids" ]; then
    echo "No cache IDs with size 0 found. Exiting."
    exit 0
    fi

    # Count the number of cache IDs found
    num_cache_ids=$(echo "$cache_ids" | wc -w)

  2. agners created this gist Nov 30, 2023.
    67 changes: 67 additions & 0 deletions prune-corrupted-layer-metadata.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,67 @@
    #!/bin/sh
    # (c) 2023 Stefan Agner
    # This scripts attempts to clear corrupted Docker overlay2 storage metadata
    # which can be left over after a power failure.
    # See also: https://github.com/moby/moby/issues/42964
    #
    # Typically the error message when attempting to pull the image for which
    # corrupted layers are in the storage looks like:
    # failed to register layer: error creating overlay mount to /mnt/data/docker/overlay2/6ee02298ee75a4f96e77f90551673cb700f29867f9ad1c4e20b8c816bfcf0735/merged: too many levels of symbolic links

    # Docker storage directory, intended for Home Assistant OS
    docker_storage_dir="/mnt/data/docker"

    # Warning message
    echo "WARNING: This script attempts to clear corrupted Docker overlay2 storage metadata."
    echo "Use with caution, as it may result in data loss. Ensure you have backups before running this script."

    # Initial sanity check for the overlay2 directory
    overlay2_dir="$docker_storage_dir/overlay2"
    layerdb_dir="$docker_storage_dir/image/overlay2/layerdb/sha256"

    if [ ! -d "$overlay2_dir" ]; then
    echo "Error: Directory $overlay2_dir does not exist."
    exit 1
    fi

    # Find unique cache IDs
    cache_ids=$(find "$overlay2_dir" -type f -size 0 \( -name lower -o -name link \) -exec sh -c 'basename $(dirname {})' \; | sort -u)

    # Count the number of cache IDs found
    num_cache_ids=$(echo "$cache_ids" | wc -w)

    # Prompt the user for confirmation
    echo "Found $num_cache_ids cache IDs with size 0. Do you want to continue and delete them? (yes/no)"
    read user_confirmation

    # Check user's response
    if [ "$user_confirmation" != "yes" ]; then
    echo "Operation canceled. No directories were deleted."
    exit 0
    fi

    # Initialize counters for summary
    deleted_cache_dirs=0
    deleted_layerdb_dirs=0

    # Iterate through cache IDs
    for cache_id in $cache_ids; do
    # Find corresponding directory in layerdb
    layerdb_dir_path=$(dirname $(grep -r -e "$cache_id" "$layerdb_dir"/*/cache-id))
    cache_dir="$overlay2_dir/$cache_id"

    # Remove cache directory
    if [ -d "$cache_dir" ]; then
    rm -rf "$cache_dir"
    deleted_cache_dirs=$((deleted_cache_dirs + 1))
    fi

    # Remove LayerDB directory
    if [ -d "$layerdb_dir_path" ]; then
    rm -rf "$layerdb_dir_path"
    deleted_layerdb_dirs=$((deleted_layerdb_dirs + 1))
    fi
    done

    # Print summary
    echo "Summary: Deleted $deleted_cache_dirs cache directories and $deleted_layerdb_dirs LayerDB directories."