Raspberry Pi - Part 18 - Backup Restore
Raspberry Pi - Part 18 - Backup Restore
-
Backup & Restore
Your Pi
Version: 2017-08-10
Backup:
This turned out to be surprisingly easy providing your Pi is connected to a NAS drive.
Use the Raspbian dd command to make an image of the SD card, which you then schedule to
run using cron.
Take a backup of the SD card using dd referencing the physical disk directory /dev/mmcblk0
and a location on the NAS drive. It doesn't have to be a NAS drive but, obviously, it does need
to be location not on the SD card, so an external USB drive should work just as well.
Depending on the size of your SD card and speed of the external drive you are connecting too,
this will take a little time, but when complete it should have created a .img file which is the
same size as the total size of your sd card e.g. if you have an 8GB sd card you will end up with
an 8GB image regardless of how much capacity is actually used.
I also stop services which run in the background (for me these are lighttpd and noip) before
starting the backup and restarted them when finished to minimise the risk of taking a backup
mid way through an update to the SD card. As I also run other scheduled jobs using cron so I
also suspend the cron service, so that other schedules jobs don't run while the backup is.
nano RunSDBackup.sh
I then schedule this job using cron and that was it, it runs once a week on a monday morning
at 2:30am. Run crontab using the -e option for edit:
sudo crontab -e
Adding the following line to the bottom of the file, then using Ctrl-X to save:
The first part "30 2 * * 1" is in the format "minute hour dayOfMonth Month
dayOfWeek" tells cron to run when the minutes on the internal clock equal 30, the hour equals
2, for any day in the month, for any month when the day of the week is Monday.
The second part is the command which outputs the results to a log file..
Restore:
You’ll end up with a .img file on your NAS share. So you can follow the usual instructions for
writing to an SD card. Then, put the SD card into the Pi and start it up.
Here's an intro to using rsync for back-up on the Pi. Once the initial back-up is created,
keeping it up to date this way is much much faster than constantly ripping the entire image.
You can do this to a local hard drive or over a network.
You actually do not want a complete copy of a running system as a back-up, since some of the
stuff ostensibly in the filesystem exists only at runtime. Including that in a backup and then
using it to recreate an image later may create problems for you.
There are some other exceptions too. Rsync can accept a list of (glob) patterns to exclude, and
those can be read from a file, so let's first go thru what should be in such a file. First note that
the entries are of the form /directory/* and not /directory. This is because we want them
to exist, but we don't want to copy anything in them.
/proc/*
/sys/*
These do not really exist on disk. They're an interface to the kernel, which creates and
maintains them in memory. If you copy these and then copy them back into a system and boot
it, it will be (at best) meaningless, since the kernel uses those as mount points for the
interfaces [If you want to see what happens when you mount a device on a directory with data
in it, try. It works and won't do any harm, but the stuff that was in the directory is now
inaccessible.]
Note that it is critical that the /sys and /proc mount points exist. But they should not contain
anything. Next:
/dev/*
The dev directory is not quite the same thing as proc and sys but for our purposes it is. If you
believe that you should save this so you can have the same device nodes in your backup or
something, you're wrong. Don't bother. Do not copy dev. Once upon a long time ago linux did
work that way, but it doesn't anymore.
/boot/*
This is sort of a special case with the pi, or at least, the raspbian image I'm using (and I
believe others such as xbmc use a similar strategy). It's actually a mount point for the first,
vfat, partition. We are going to deal with that separately. Whatever you do, don't bother
including it here, because again, it's a mount point.
/tmp/*
/run/*
With the (debian based) pi /run is not on disk either, it's in memory. Perhaps /tmp could be
too (this would save a bit of SD card action), but in any case, as the names imply, these are
not places for storing persistent data. Copying and restoring these can cause problems
because various userland tools store state information there and if you reboot with that, they
may end up confused.
/mnt/*
This one is pretty important if you are planning to back up to a hard drive and the hard drive is
in /mnt, hopefully for obvious reasons. Rsync might be smart enough to spot something that
dumb (I have not tested it) but if not, you might end up filling the drive with the same thing
over and over and over. Or something. So exclude mnt.
/media/*
/proc/*
/sys/*
/dev/*
/boot/*
/tmp/*
/run/*
/mnt/*
.bash_history
/etc/fake-hwclock.data
/var/lib/rpimonitor/stat/
If you might find other files or directory that aren’t usefull to you, just add them to the
/rsync-exclude.txt file
Now create a directory to back up to, eg, "pi_backup". If the above file is /rsync-exclude.txt
and your drive is /mnt/usbhd, to do the actual backup:
mkdir /mnt/usbhd/pi_backup
rsync -aHv --delete-during --exclude-from=/rsync-exclude.txt / /mnt/usbhd/pi_backup/
This will take a while and produce a lot of output (if you want to examine that in a log instead,
append > rsync.log). --delete-during is meaningless the first time, but for keeping the
backup updated use it. This ensures that stuff you've later deleted on the pi also gets removed
from your backup.
-a sets recursion into directories and makes sure all the file attributes match.
-H is to preserve hard links.
-v is for verbose which is why you get some output, otherwise rsync is quiet.
See man rsync for more.
There is a shortcut whereby you can skip the --exclude-from file. If you are sure that all of
the things you don't want to copy (/tmp etc.) are on separate filesystems, you can just use:
-x has been inserted. This is the short form of --one-file-system, which tells rsync not to
cross filesystem boundaries. Personally I prefer the --exclude-from, but on e.g., default
Raspbian, --one-file-system will work fine.
That's not quite a complete backup. It's enough if you haven't put anything in boot and you
are fine with using the back up to just restore the system by sticking the card in a computer
and running:
You could also do this with a card with a new image on it (presuming it's the same as your
base image) although that's a little inefficient if you have to create the image (because you're
If you've put stuff in /boot (eg, a custom kernel), including /boot/config.txt, you'll want to
back that up too (pretty simple -- there's not much to it). Just do it separately, and when you
restore, that stuff goes in the first partition.
Backup:
Restore:
Using rsync, once a backup exists, updating it is much much faster, so you can set this up to
happen painlessly everyday via cron.
You can use rsync even over a network using rsync via ssh
Here's an example:
If you backup to an ext4 partition on a HDD mounted on the Pi and if the HDD is not mounted,
rsync would copy to the mount directory until the SD Card is full.
If the HDD is not mounted in rw mode copious error messages are produced.
Neither of these is desirable, so let’s check that the partition is mounted in rw mode before
proceeding.
#!/bin/bash
# script to synchronise Pi files to backup
BACKUP_MOUNTED=$(mount | awk '/usbhd / {print $6}' | grep "rw")
if [ $BACKUP_MOUNTED ]; then
echo $BACKUP_MOUNTED
echo "Commencing Backup"
rsync -avH --delete-during --delete-excluded --exclude-from=/rsync-exclude.txt /
/mnt/usbhd/pi_backup/
rsync -axHv --delete-during /boot /mnt/usbhd/pi_backup/boot/
else
echo "Backup drive not available or not writable"
fi
rpi-clone is a shell script that is for cloning a running Raspberry Pi booted source disk (SD card
or USB disk as you can boot from USB stick as well) to a destination disk which will be
bootable. Destination disks can be SD cards in the SD card slot or a USB card reader, USB
flash disks, or USB hard drives.
I will only describe what I have tested succedful. See the README.md for detailed information.
My aim was to clone the SD card to and SD card inserted in a USB slot with an adapter. This
would give me a ready-to-replace bootable spare SD card of my PI.
Install
rpi-clone is on github and is downloaded by cloning the repository. It is a standalone script and
the install is a simple copy to a bin directory. When run it checks its program dependencies
and offers to install needed packages.
echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:
Note: rpi-clone-setup is for setting the different hostname in /etc/hostname and /etc/hosts
files of the clone. So your backup SD card will have a different hostname. This can be handy if
you want to setup several Raspberry Pi’s eg: a training class and make sure all have a different
hostname. It is run automatically by rpi-clone if -s args are given, but before your first clone
using a -s option, test run rpi-clone-setup with:
And check the files under /tmp/clone-test to be sure the files have been edited correctly.
If you need additional customizations to a clone, add them to the rpi-clone-setup script.
sudo rpi-clone
Typical two partition clones - SD card to USB disk (= backup of SD card to USB disk):
rpi-clone sda
USB boot , clone back to SD card slot ( = restore from USB disk to SD card) :
rpi-clone mmcblk0
Note 1: make sure you have installed the package usbmount. If not, run first the following
Note 2: Remove any partition from the destination USB stick, create 1 FAT32 formatted
partition on it. You can use the Diskmanager of Windows to do so.
df -h
Now insert the USB stick in a USB slot, wait 10 seconds and type again
df -h
Now you should see that the USB drive is mounted as sda. If there are several partitions on
the USB drive, you will see sda1, sda2, …
rpi-clone sda
Initializing
Imaging past partition 1 start.
=> dd if=/dev/mmcblk0 of=/dev/sda bs=1M count=8 ...
Resizing destination disk last partition ...
Resize success.
Changing destination Disk ID ...
=> mkfs -t vfat -F 32 /dev/sda1 ...
=> mkfs -t ext4 -L boot /dev/sda2 ...
fdisk -l
Next, partition it
fdisk /dev/sda
> n
> p
> 1
(size the partition)
> a
> 1
(toggles boot flag)
> t
> c
(filesystem type)
> p
(prints current configuration)
> w
(write the new table and quit)
mkfs /dev/sda1