Skip to content

Instantly share code, notes, and snippets.

@joshenders

joshenders/recover.sh

Last active Jan 5, 2016
Embed
What would you like to do?
ddrescue recovery script
#!/bin/bash
function exit_with_usage() {
# usage: exit_with_usage
echo "Usage: ${0##*/} <src> <dest>" >&2
exit 1
}
function prompt() {
# usage: prompt "prompt message"
local message="$1"
local response
while [[ -z "${response}" ]]; do
read -p "${message} [y/n] " response
if [[ "${response}" =~ ^[yY]$ ]]; then
printf "\n"
return 0
elif [[ "${response}" =~ ^[nN]$ ]]; then
return 1
else
unset response
fi
done
}
function pprint_hdparm() {
# usage: pprint_hdparm "device"
local device="$1"
local pattern='Model\ Number
|Serial\ Number
|Firmware\ Revision
|(Logical|Physical).*Sector\ size
|device\ size\ with\ M'
hdparm -I "${device}" | egrep "${pattern}"
}
function main() {
if [[ "$#" -ne 2 ]]; then
exit_with_usage
fi
local src="$1"
local dest="$2"
# Prevent Seagates from getting clobbered
local dest_model=$(hdparm -I "${dest}" \
| awk -F: '/Model\ / { gsub(/^\ +/, "", $2);
print $2; }')
local pattern='^ST'
if [[ "${dest_model}" =~ ${pattern} ]]; then
exit_with_error "Refusing to overwrite ${dest}"
fi
# Source
echo 'Source: '
pprint_hdparm "${src}"
# Destination
echo 'Destination: '
pprint_hdparm "${dest}"
prompt 'Continue?' || exit $?
local serial=$(hdparm -I "${src}" \
| awk -F: '/Serial\ Number/ { gsub(/ /, "");
print $2; }')
local bs=$(hdparm -I "${src}" \
| awk -F: '/Physical.*Sector\ size/ { gsub(/bytes/, "");
gsub(/ /, "");
print $2; }')
# First backup all error-free areas
ddrescue \
--block-size="${bs}" \
--force \
--no-split \
"${src}" "${dest}" \
"${serial}".log
# Then try to recover any bad sectors
ddrescue \
--block-size="${bs}" \
--direct \
--force \
--max-retries=3 \
"${src}" "${dest}" \
"${serial}".log
# Last, retrim?
# ddrescue --retrim --complete-only
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment