#!/bin/bash
# try to recreate damaged files on faulty hardisks using the gnu-ddrescue tool
#
# Hardisks normaly don't verify data written to the media, under certain conditions
# it can happen that data written will not be readable again. Usally the hardisks
# firmware can handle this transparently by applying error correction codes and
# replace bad sectors with spare sectors before this causes problems. In rare cases
# one might still discover a read error passed to the OS/Application.
# This tool tries its best to recreate such a damaged file.
#
# usage:
#  salvage.sh [find options]
#
# example:
#  badblocks /dev/hda || salvage.sh /
#
# for each rescued file a filename~salvlog is left behind which marks the regions 
# of missing data, see the ddrescue documentation for details.
#
# important notes:
#  It is important to check a partition before running this with the
#  'badblocks' tool, simple readonly mode suffices an can be run while the partition
#  is mounted. The rationale for this is, that the harddisks firmware will map
#  unreadable sectors to spare sectors on the first *write*, so detecting bad sectors
#  early is important for success. Running such a badblocks scan regulary is likely
#  not a bad idea anyways.
#
# WARNING:
#  Keep an eye on the badblocks output and make regular S.M.A.R.T. checks. This script
#  does not repair damaged disks it only delays their ill effects. It may even give
#  you a feel of wrong safety!
#  WHEN A DISK FAILS AND STARTS ACCUMULATING ERRORS THEN REPLACE IT!

find "$@" -type f -size +0 -printf "%D %i '%p'\n" | sort -n | uniq -t ' ' -W 2 | while read inode file; do
        file=${file:1:${#file}-2}
        if test -e "$file"; then
                echo -n "CHECKING '$file'"
                if ! cat "${file}" >/dev/null; then
                        echo " SALVAGING"
                        ddrescue -qr3 "$file" "${file}~salv" "${file}~salvlog"
                        if cat "${file}~salv" >/dev/null; then
                                echo "  SALVAGED '$file'"
                                ddrescue -q "${file}~salv" "$file"
                                if cmp "${file}" "${file}~salv"; then
                                        echo "    RECREATED '$file'"
                                        rm "${file}~salv"
                                else
                                        echo "    RECREATE FAILURE, ${file}~salv ${file}~salvlog left behind"
                                fi
                        else
                                echo "  FAILED"
                                rm "${file}~salv" "${file}~salvlog"
                        fi
                else
                        echo " OK"
                fi
        else
                echo "DELETED $file before beeing checked"
        fi
done
salvage.sh

caveats

salvage.sh (last edited 2006-04-01 12:02:50 by ct)