Skip to content

Instantly share code, notes, and snippets.

@hackman
Created November 14, 2021 23:52
Show Gist options
  • Save hackman/e67008769ceee13f28827745ec2204f8 to your computer and use it in GitHub Desktop.
Save hackman/e67008769ceee13f28827745ec2204f8 to your computer and use it in GitHub Desktop.
Script to copy data from broken hard drive with DD :)
#!/bin/bash
dst_drive=/dev/sda
src_drive=sdd
skip_drive=sdb
dd_status=/tmp/dd
log_file=/tmp/dd.log
size_file=/tmp/last_size
slot=32:1
reactivate_drive() {
while true; do
# Firmware state: Online, Spun Up
if MegaCli -pdInfo -PhysDrv[$slot] -a0|grep -q 'Online'; then
break
fi
# Foreign State: Foreign
if MegaCli -pdInfo -PhysDrv[$slot] -a0|grep -q ': Foreign'; then
MegaCli -CfgForeign -Clear -a0 >> $log_file 2>&1
sleep 1
fi
# Firmware state: Unconfigured(good), Spun Up
if MegaCli -pdInfo -PhysDrv[$slot] -a0|grep -q 'Unconfigured(good)'; then
MegaCli -CfgLdAdd -r0[$slot] WT NORA Direct -a0 >> $log_file 2>&1
break
fi
sleep 2
done
}
start_copy() {
skip_size=0
skip_file_size=0
if [[ -f $size_file ]]; then
skip_size=$(<$size_file)
skip_file_size=$skip_size
fi
# Get the last drive name :)
src_drive=$(awk '/sd.$/{a=$4}END{print a}' /proc/partitions)
if [[ $src_drive =~ sd[ab] ]]; then
echo "Wrong drive: $src_drive"
return 1
fi
if [[ -f $dd_status ]]; then
# dd: error reading '/dev/sdd': Input/output error
# 2926+1 records in
# 2926+1 records out
# 30687887360 bytes (31 GB, 29 GiB) copied, 242 s, 127 MB/s
# MB/10 because of the bs=10M. So we get the value of the MB copied and then devide it by 10
skip_size=$(awk '/copied/{a=$1}END{a=int(a);a=a/104858;a=int(a);if(a>400){a-=200}else{if(a>200){a-=100}};print a}' $dd_status)
skip_size=$(($skip_size + $skip_file_size))
echo $skip_size > $size_file
fi
echo "dd if=/dev/$src_drive of=$dst_drive bs=10M skip=$skip_size seek=$skip_size> $dd_status 2>&1" >> $log_file
dd if=/dev/$src_drive of=$dst_drive bs=10M skip=$skip_size seek=$skip_size > $dd_status 2>&1
dd_code=$?
cat $dd_status
if [[ $dd_code == 0 ]]; then
echo "DD finished successfully"
return 0
else
return 1
fi
}
count=0
start=$(date +%s)
elapsed_time=0
while true; do
let count++
now=$(date +%s)
elapsed_time=$(($now - $start))
size=0
if [[ -f $size_file ]]; then
size=$(<$size_file)
fi
printf "%s Starting run %4d - %12d GB copied - elapsed time: %d\n" "$(date +'%d.%b %T')" $count $size $elapsed_time
reactivate_drive
if start_copy; then
break
fi
sleep 20
done
printf "%s Finished in %4d runs. Total time: %d\n" "$(date +'%d.%b %T')" $count $elapsed_time
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment