How to switch ddrescue from `/dev/sdq1` to `/dev/sdq` if I've already backed up data from `/dev/sdq1`?
I started to recover my /dev/sdq1
when I was not familiar with HDD recovery. Well, I was careful enough and recover 85% in about 500 runs.
Afterwards, I've found out that I need /dev/sdq
(without 1) contents actually to convert them after to .vhd
with VBoxManage convertdd z:\fixed.vdi d:\disc.vhd --format VHD
and after I can attach and read that .vhd
in Windows, because VBoxManage
does not support partition conversion and requires full harddrive raw data as an input. That means I should have started ddrescue with /dev/sdq
and not /dev/sdq1
.
I've found out that contents of /dev/sdq1
start at 32256 byte of /dev/sdq
with fdisk. I dd
ed these bytes at the beginning to separate file begin.raw
and now running cat ./rescue/begin.raw ./rescue/fixed.vdi > ./sdq.raw
to prepend them to recovered data from /dev/sdq1
.
Is there an easier way to continue runs of ddrescue
to that new ./sdq.raw
with old rescuelog? I'm not sure that --output-position
will fit here. (and how does it work exactly? -- This is not clear from docs how output-position
will influence on rescuelog interpretation).
I don't want to copy 500GB each time I want to get my ./sdq.raw
.
Below is my script I use to recover data. Sometimes I had to detach HDD physically because my usb hub does not support complete power off on its ports.
#!/bin/bash
function run {
ddrescue -T 5s --max-error-rate=10MB --skip-size=512KiB,10MiB \
--direct -vv -P /dev/sdq1 ./fixed.vdi ./rescue.log
}
while true; do
run &
JOBPID=$!
while true; do
dmesg | tail -1 | grep 'reset high-speed USB device number' > /dev/null
CODE=$?
if [ $CODE -eq 0 ]; then
break
fi
kill -0 "$JOBPID" > /dev/null
CODE=$?
if [ $CODE -ne 0 ]; then
break
fi
sleep 3
done
./uhubctl -i -a 2 -p 1 -l 1
wait $JOBPID
echo "MSG: waiting for re-attach"
until dmesg | tail -1 | grep 'Attached SCSI disk'; do sleep 1; done
sleep 5
done
Thanks!
P. S. I have Logitech USB 2.0 hub but it does not support full poweroff on ports either with uhubctl
. Maybe there's other tool that can work with it?
Regardless of whether --output-position
is the right ddrescue
option or not, I present the general Linux way to concatenate two files without writing the result to disk.
The tool is dmsetup
. It is in the dmsetup
package in my Kubuntu, the same in Debian.
We have begin.raw
of the size 32256 B
and fixed.vdi
corresponding to the partition of the size <X>
(about 500 GB
, the exact value unknown to me). We need to express the sizes in 512 B
unit; the results are 63
and <Y>
respectively. In the code below you have to replace <Y>
with the computed value, so don't copy-paste it mindlessly.
# Creating loop devices and storing their names.
BEGIN_LOOP=$(sudo losetup -f --show begin.raw)
FIXED_LOOP=$(sudo losetup -f --show fixed.vdi)
# Creating a map to feed to `dmsetup` later.
# !!! REPLACE <Y> WITH THE PROPER VALUE !!!
echo "0 63 linear $BEGIN_LOOP 0" > whole.map
echo "63 <Y> linear $FIXED_LOOP 0" >> whole.map
# Creating a concatenated "file".
sudo dmsetup create whole.raw < whole.map
ln -s /dev/mapper/whole.raw
You can now use whole.raw
as an image of the entire disk while ddrescue
may still work with fixed.vdi
. Every I/O operation on whole.raw
will be mapped to begin.raw
and fixed.vdi
.
Note that this mapping is not persistent. After a reboot you need to repeat the whole procedure except ln -s
.
To clean this setup without rebooting, invoke:
rm whole.raw # removes the symlink
sudo dmsetup remove whole.raw # removes /dev/mapper/whole.raw
sudo losetup -d $FIXED_LOOP # removes /dev/loop1 (or so)
sudo losetup -d $BEGIN_LOOP # removes /dev/loop0 (or so)
If you lose the variables somehow (e.g. by closing the terminal emulator) then examine the output of losetup -a
and do sudo losetup -d /dev/loopX
accordingly.