0

I have two the same capacity drives (equal to 1 byte). I need to swap their content (one is QVO, other one is EVO, but the selection of their application was mistaken).

Is it possible to do that by pipes or FIFO in Linux?

I am thinking about eventually storing 100/500 MB of each drive at one moment (on Linux drive or in memory) and rewrite it but to the other disk, repeating the process.

I know dd and third disk but need to operate only on these two. Both disks are 1 TB SSD, where one is 70% full, and the other has basic Linux system with no more than 20 GB of data.

I agree that there is third medium with OS (in this case Linux) but this disk has limited free space, let's say we can use up to ~1 GB so we can't make full disk image (even compressed).

pbies
  • 2,757
  • 3
  • 21
  • 23

3 Answers3

2

One solution would be a bash script.

Be aware that using a third drive is the preferred way and using a script is kind of a suicide mission !!

Therefor, just use this approach if you don't have (or can't get access to) a third drive and you're desperate !! You've been warned !!

#!/bin/bash

DRIVE1="${1}"
DRIVE2="${2}"
BS="${3:-16M}"
block="${4:-0}"
TMP="$( mktemp ~/$$.XXXX )"

while true; do
  dd if=$DRIVE1 of=$TMP bs=$BS skip=$block
  dd if=$DRIVE2 of=$DRIVE1 bs=$BS skip=$block seek=$block
  dd if=$TMP of=$DRIVE2 bs=$BS seek=$block || break
  block=$(( block += 1 ))
  echo $block > ~/block.info
done

Copy the code above to a file and make it executable (chmod +x filename). Then you can call the script with sudo ./filename /dev/sdX /dev/sdY 16M whereby
- /dev/sdX should be the first drive (e.g. /dev/sda and not /dev/sda1 !!)
- /dev/sdY should be the second drive
- 16M is the chosen blocksize (16M stands for 16 MB, could also be 32M, 64M, 128M, 256M, ...)

bey0nd
  • 455
  • 2
  • 8
  • **WARNING** The problem with this kind of procedure is it's easy to mess it up. Even if your script is good *when everything goes well*, it's flawed *when something goes wrong*. What if there's a critical failure (power outage?) when `~/block.info` is not yet synced to the disk? How to recover from a read error, if one occurs? And if I'm not mistaken, `break` leads to `rm`. This is *fatal*, data gets lost. I don't want to downvote, the answer has a potential; but I wouldn't use it in its current form. (Side note: [quote!](https://unix.stackexchange.com/a/131767/108618)) – Kamil Maciorowski May 14 '20 at 16:32
  • @KamilMaciorowski As the `break` is the exit of the `while true;` loop and the `rm` was the cleanup, this was just how it was meant to be. Now it has to be cleaned up manually. ;-) – bey0nd May 14 '20 at 17:56
  • Manually is better. Otherwise if the third `dd` failed for some unexpected reason, you would lose the temporary file. The original chunk would have already been overwritten by the second `dd`, the file would be the only copy, now gone. You need to anticipate such things. – Kamil Maciorowski May 14 '20 at 18:08
  • @bey0nd I like this resolution for the idea even if it is not safe. `block` is missing $ sign. Seems like the other answer is proper for safe swap, but not the answer to the question. – pbies May 14 '20 at 18:18
  • @pbies Which `block` are you referring to? A name of a variable within $(( )) doesn't require a `$` sign ! – bey0nd May 14 '20 at 18:19
  • @bey0nd 6th line of the code - the "4:". – pbies May 14 '20 at 18:23
  • I am selecting this answer as the solution but I surely say that this solution is not safe. Idea here is more important than application. – pbies May 14 '20 at 19:25
0

What i've done in past was to make exact clone of each disk to free storage on seperate disk, and then cloned them back to intended disks, plus clones help to prevent loss of data when things go wrong. In windows i use "disk clone free" that allows you to make clone of partition even if destination partition is smaller, also allows to copy hardware disk ID's or not, nice if disks aren't the same size.

For linux Try the command "dd", but be careful, it can go way wrong if you get it wrong... some tips on dd at below link https://opensource.com/article/18/7/how-use-dd-linux

Meant to be more of a comment this part...bit long though

pbies, not sure about partitioning on disk here, let say you have single part on disk A with 700GB data, Disk B also single part with 20GB data, create new partition on disk B with the free space available, clone disk A to New partition on diskB, now you have both copies on disk B in tact. Now prepare disk A to receive disk B's clone as primary and disk A's original clone as secondary part, now this leaves Disk B free to prepare its partitions to receive disk A's clone as primary, probably best to boot live linux CD to do all this... hope one of these smart guys can give some more input on exactly how this is done in linux and what works best for the cloning and partitioning procedures (ddrecue etc) It makes sense to me ,, not sure if others agree ??

Andy
  • 1
  • 1
0

This answer is not meant to help in a general case of "swapping content of two drives of identical capacity". It is tailored to the specific problem:

Both disks are 1 TB SSD, where one is 70% full, and the other has basic Linux system with no more than 20 GB of data.

The procedure, in short, just to let you know what we're going to do:

  1. Read disk A and store its image (compressed or sparse, compare this) inside a filesystem on disk B.
  2. Fully duplicate disk B to disk A, along with the image of the original A.
  3. Read the image from A and write it to B.

In detail:

  1. Decide which disk is which:

    diskA=/dev/sdx    # choose disk with little data
    diskB=/dev/sdy    # choose disk with lot of data
    
  2. Mount each filesystem of disk A and trim it:

    fstrim -v /the/mountpoint
    

    Then unmount. You can do this one filesystem at a time. Do this also for at least one filesystem on disk B, the one you plan to write an image to.

    More about trimming here, here and here. The point of it is twofold:

    • reading from disk A should now bring us many blocks of zeros which are highly compressible (this answer applies to HDD, HDD needs zeros to be explicitly written; but this answer states you only need to trim SSD to achieve a similar result);
    • disk B is now ready to store an image of disk A.
  3. Mount the chosen filesystem of disk B.

  4. Make sure no filesystem of disk A is mounted. Read the entire disk A and store its image compressed or sparse in the filesystem of disk B. This example uses compression (and pv to show the progress):

    <"diskA" pv | gzip -c >/the/mountpointB/image.gz
    
  5. Unmount the filesystem of disk B.

  6. Make sure no filesystem of disk B is mounted. Clone disk B to disk A. You can do this with dd, cat, cp, ddrescue, there are many tools. This example uses pv:

    pv "$diskB" > "$diskA"
    

    Now you have two copies of disk B, each containing the image of disk A.

  7. Remove the partition table or filesystem signature from disk B. This is very important if disk B uses BTRFS (so now also A uses it). The potential problem is if you try to mount a BTRFS filesystem and it is found in two copies (same UUIDs) then it will be considered a muli-device filesystem; mounting it may cause data loss. In the next step we will mount a filesystem from disk A (a copy of B), so be careful.

    wipefs -a "$diskB"
    partprobe
    
  8. Mount the copy of the filesystem you used to store the image of disk A. Remember the copy is now on disk A.

  9. Restore the data from image.gz to disk B. This way the original content of disk A is moved to disk B:

    </the/mountpointA/image.gz gzip -dc | pv >"diskB"
    
  10. Mount each filesystem of each disk and trim it. You can do this one filesystem at a time.

Note if any step fails then you will still be able to recover relatively easily. This is because each time you actually overwrite data, the other disk contains a valid copy.

Kamil Maciorowski
  • 69,815
  • 22
  • 136
  • 202