Saturday, April 23, 2005

Cloning XP with Linux and ntfsclone

I recently had two different occasions where I wanted to clone Windows XP on a few identical machines. The first time, I cloned the entire disk, bit by bit, using the dd and netcat method described in a previous post. That worked very well, but was very slow: several hours for a little 40 GB disk over a Gigabit link.

This time, I had 80 GB disks, and I not only wanted to clone the machine, but also to keep the image as a backup. So I wanted a method which would not blindly copy the whole disk, but only the parts of it that are really in use.

The partitions being NTFS, I tried ntfsclone. After falling into a few traps (completely unrelated to ntfsclone itself), it worked perfectly, and was pretty fast (using Gigabit Ethernet). So here is the recipe, for myself when I will need it again, and for whoever may find it useful:


  • The machine to clone which I will boringly call Master.
  • The new clone, unsurprisingly called Slave here, and which is assumed to be made of identical hardware, particularly the hard disk.
  • Gigabit Ethernet.
  • A server for the Master disk image
  • A Linux "Live CD" (I used Knoppix 3.8.1, which had ntfsclone version 1.9.4).

The Backup:

Boot Master from the Linux live CD

Open a root shell

Set my swiss keyboard layout if needed
# setxkbmap fr_CH
or in newer versions:
# setxkbmap ch fr or setxkbmap ch de

Check if the network is up
# ifconfig eth0

It wasn't for me, and DHCP tended to fail for some reason, so I configured it manually:

# ifconfig eth0
# echo nameserver > /etc/resolv.conf
# echo search example.lan >> /etc/resolv.conf
# route add -net gw

The machine displaying a stupid time and time zone, I also did
# tzselect
and pasted the string it suggested on the command line,
# TZ='Europe/Zurich'; export TZ
and then set the clock:
# ntpdate
# hwclock --systohc

This was not really necessary, but I noticed that the file times on the server would be wrong if the client had a wrong time and/or time zone.

And now the real stuff:

Create a mount point
# mkdir /tmp/server

Mount the server's share. I used a share called diskimages on a Samba server, but it could have been Windows, an NFS server, or whatever.
# mount -t smbfs -o username=my_user_name   //server_name/diskimages /tmp/server

Check how your live CD called the partitions you want to save
# cat /proc/partitions
major minor #blocks name

8 0 78150744 sda
8 1 20482843 sda1
8 2 1 sda2
8 5 20482843 sda5
8 6 37182411 sda6
180 0 253952 uba
180 1 253936 uba1
240 0 1939136 cloop0

I want to save that 80 GB disk sda, which has a primary partition sda1,
and an extended partition sda2 containing logical partitions sda5 and
sda6. So what I want to save is sda1, sda5 and sda6.
First I saved the partition table and the Master Boot Record
# sfdisk -d /dev/sda >/tmp/server/master-sfdisk-sda.dump
# dd if=/dev/sda bs=512 count=1 of=/tmp/server/master-sda.mbr

and then the partitions:
ntfsclone -s -o - /dev/sda1   | gzip | split -b 1000m - /tmp/server/master-sda1.img.gz_
ntfsclone -s -o - /dev/sda5 | gzip | split -b 1000m - /tmp/server/master-sda5.img.gz_
ntfsclone -s -o - /dev/sda6 | gzip | split -b 1000m - /tmp/server/master-sda6.img.gz_
This is where I fell into the first trap. My Samba server doesn't seem to accept files larger than 2 GBytes! That is why the output is piped through split. I still don't know why I cannot write files larger than 2 GB, and if you do, please let me know. This is a Samba 3.x server running on Debian with a 2.6.x kernel, and the share is on a 36GB ext3 partition.
(update: this comment suggests to add the lfs option to smbfs mount. This allowed me to write more than 2 GB, but not more than 4GB. Probably because it's a FAT32 partition)

Anyway, split solved that problem nicely, chopping the output into 1 GB files, but I had added gzip in the hope of making things faster, and that gzip and split combination bit me later. And I'm not even sure that the gzip overhead is worth the bandwidth saving. Gigabit Ethernet can be really fast. In fact, it can be faster than the hard disks. That may be worth benchmarking some time. (I also tried bzip2, which has better compression, but that was excruciatingly slow).

That's it for the backup. Now, to the next part:

The Restore:

Boot Master from the Linux live CD, and proceed as for the backup:

setxkbmap fr_CH
ifconfig eth0
echo nameserver > /etc/resolv.conf
echo search example.lan >> /etc/resolv.conf
route add -net gw
TZ='Europe/Zurich'; export TZ

hwclock --systohc

mkdir /tmp/server
mount -t smbfs -o username=my_user_name //server_name/diskimages /tmp/server
(I just copied/pasted this whole block into the shell)

Check your partitions again, and make sure you will not overwrite some other disk!

# cat /proc/partitions

Now I first restored the partition table and the master boot record

# sfdisk /dev/sda < /tmp/server/master-sfdisk-sda.dump
# dd if=/tmp/server/master-sda.mbr of=/dev/sda

And then the partitions. Since I had several files produced by split for my primary partition, I needed to take them all, in the right order of course. split adds "aa", "ab", "ac", etc. to the end of the file name.

# ls -l /tmp/server

will help you check which files you need

This is where the second trap got me. gunzip's documentation led to believe that I could do something like gunzip -c file1 file2 file3 | ntfsclone ... which would be the same as cat file1 file2 file3 | gunzip -c | ntfsclone ...

Well, it is not the same, and my first tries would result in the process aborting after a (long) while, with the error "gunzip: unexpected end of file".

Eventually, it worked:
cd /tmp/server
cat master-sda1.img.gz_aa master-sda1.img.gz_ab master-sda1.img.gz_ac | gunzip -c | ntfsclone --restore-image --overwrite /dev/sda1 -
cat master-sda5.img.gz_aa | gunzip -c | ntfsclone --restore-image --overwrite /dev/sda5 -
cat master-sda6.img.gz_aa | gunzip -c | ntfsclone --restore-image --overwrite /dev/sda6 -
Reboot into your new Windows XP clone.

Now I wonder if there is anything I overlooked with machine IDs (SID?) and such, but I haven't seen a problem so far.
Do I need to do something, to change the SID of the clone?

If you don't need to save the image and want to be faster, you could of course combine this method with netcat and skip the server.

Labels: , , , ,