#!/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
- needs to be checked with raid (failing reads might put a disk into faulty mode)
- optional non-in-place mode is needed for unattended operation (restored files don't
- have read errors but their data might be corrupt, that can be problemeatic!)
- this recovers only files, to recover filesystem metadata you have to run a fsck