All right, you’ve spent countless sleepless nights working on that ultra cool Raspberry Pi project, and now you’re thinking about the unthinkable. What happens if my Raspberry Pi or SD Card dies? Do I have a backup? Can I quickly get up and running? The answer is probably NO.
So being an avid Raspberry Pi hobbyist, I’ve probably already piqued your interest. You also probably already know that the SD Card in your Pi is like a ticking time bomb – waiting to go off at the slightest movement and prompting you to curse loudly in your mother tongue. That cheap SD Card indeed has a set number of writes and not to mention is quite prone to data corruption from various sources. Oh my, what to do…
So now that I’ve scared you silly, I’ll go over some backup options that you yourself can follow to prevent the unthinkable from happening. Some easy, others more technical. In the end, you’ll be equipped with what you need to stave off a night of aggravation and profanity.
Update: July 2017
It has been brought to my attention by reader Anton that the latest version of Raspberry pi OS has a built in software that does an exact copy of the SD card. What’s needed is a USB card reader with a new empty SD card. So assuming you are running a recent version of Raspbian Jessie, the SD Card copy utility is under Accessories. It handles different sized cards (even larger to smaller) automatically.
Type of Backups
I like to separate the backup methods into three possible scenarios:
- Block per block copy
- Shrink, then copy
- File based copy (live option)
Requirements
If you don’t already have, I highly recommend to purchase a USB SD Card Reader. I have something like this:
1. Block per block (1-to-1 copy)
Back to it. A block per block copy usually involves using a tool like dd (on Linux / Mac OS X) to perform the backup or dump.
A command like dd copies data from one location to another, overwriting existing data as it goes. Needless to say, this can be dangerous and is most certainly irreversible. Don’t blindly copy the commands below without ensuring they’re applicable to your specific case – adapt them if necessary. Don’t use dd while sleep deprived. You have been warned.
Advantages
- Relatively simple with the right OS
- dd is a workhorse and quite robust
- Availability (installed by default on Linux / Mac OS X, Windows version exists)
Disadvantages
- Time consuming
- Resulting file size large (same size as source disk w/o compression)
- Dangerous if you don’t know what you are doing
- Can only restore to similar sized SD Cards or bigger
Steps
The first step in using this tool is getting your SD Card in your reader, connecting it to either a Mac or Linux PC and determining the disk identifier you’d like to copy from.
On MAC:
diskutil list
On Linux:
sudo fdisk -l
If you’re on Windows, please refer to Win32DiskImager. However, the rest of this post will assume you’re on a Linux based PC.
Once you know the disk identifier you can begin the backup. The dd command is straight foward. if for input and of for output, bs stand for the block size – I typically use 1m here. pi.img is your image. So assuming your SC Card is rdisk1 or sda, the command is as follows.
On MAC:
sudo dd if=/dev/rdisk1 of=./pi.img bs=1m
On Linux:
sudo dd if=/dev/sda of=./pi.img bs=1m
Restoring the image is just as easy except the if and of parameters are reversed.
On Linux:
sudo dd if=./pi.img of=/dev/sda bs=1m
As noted earlier this produces a file with the same file size as the source SD Card. So if you got a 32GB card, you’ll end up with a close to equal file size which could be quite wasteful, especially if you’re using only 3GB of that card in your running system. You could potentially mitigate this a little with compression by using gzip but don’t expect miracles. Unless you zero-out all that empty space prior to running a backup (and I won’t be going into that here), you’ll probably see little improvement. Again, your mileage will vary here as it relates to file size.
Backup:
sudo dd if=/dev/rdisk1 bs=1m | gzip > ~/Desktop/pi.gz
Restore:
gzip -dc ~/Desktop/pi.gz | sudo dd of=/dev/rdisk1 bs=1m
2. Shrink, then copy
This method involves reducing the size of the main Linux partition on the SD Card and then performing the backup – all done on another PC, preferably one running Linux. A tool like GParted or similar is instrumental here. I employed this technique in the series of blog posts devoted to installing a Triple Boot System on the Pi. I suggest you take a look there.
In short the process is something like this: on a Linux based system attach your SD Card into a reader, shrink the Linux Partition (ext4) to something that just encompasses the data within it. Then perform a backup using dd of the boot (fat32) and linux (ext4) partitions. To restore: plop the new SD Card in, create the partitions, restore and resize the ext4 partition. Again take a look at the following blog post for more info: Triple Boot Raspberry Pi on USB (Raspbian / RetroPie / OpenELEC) – Part 2.
Advantages
- Resulting file sizes are small
- Can restore to any size SD Card
Disadvantages
- Time consuming and more complex
- Dangerous if you don’t know what you are doing
Steps
Visitor abracadabricx was kind enough to provide a script. Please see the comments section below for his work. Thanks again!
3. File based copy (live option)
A third and final option is using Rsync to perform a file based copy.
rsync is a widely-used utility to keep copies of a file on two computer systems the same. It is commonly found on Unix-like systems and functions as both a file synchronization and file transfer program
The good news here is that your don’t need to understand too much about the rsync command as many scripting geniuses out there have done the dirty work for us. I wholeheartedly suggest using a script called rpi-clone to make your backup. The script is run on a live Raspberry Pi system which sets it apart from the previous two methods I just described. You’ll once again need a USB Card reader, this time directly connected to your Raspberry Pi.
Advantages
- Easy as Pi (sorry, that was lame…)
- Can restore directly to an SD Card
- Can restore to any size SD Card
- Can provide incremental backups
Disadvantages
- Runs on a Raspberry Pi live system
- Problematic when running other disk writing programs or applications
Steps
To install, login to your Raspberry Pi via a terminal. Go to https://github.com/billw2/rpi-clone and download the zip file:
unzip rpi-clone-master.zip cd rpi-clone-master cp rpi-clone /usr/local/sbin
or, use git to clone the repository:
git clone https://github.com/billw2/rpi-clone.git cd rpi-clone cp rpi-clone /usr/local/sbin
Next, put your new SD Card into the USB card reader and connect it to the Raspberry Pi. Determine the Linux device of the destination SD card (refer to method 1. for Linux), hint: it’s usually sda. Now issue the command as root and sit back and watch files fly by your terminal in awe…
sudo rpi-clone sda -v -x
Recap
As that unusual and bewildering expression goes, there’s more than one way to skin a cat. And in the same vain, I’m sure there’s many more ways to backup a Raspberry Pi SD Card that I’m neglecting to mention. But as it stands now, for me, method 3 is by far the easiest and quickest.
I do hope it’s given you ample knowledge and courage to perform your very own Raspberry Pi backups. Be well and keep on tech’ing!
Hi, I recognise your story, I have a few of those projects….. To alleviate the two disadvantages of your second approach I wrote a rudimentary bash script. The approach is to take the sd card from the PI and slot it in some linux computer that you use to make a backup. The script measures and calculate a minimum image size, shrinks the filesystem and subsequently the partition on the sd card, which is quite fast. After that it writes an image of only those blocks that are part of the resized partitions to a location of choice. It works well, and all images made have been succesfully tested. You’re welcome to use or share it, and I’ll be happy to learn how it could be improved. Let me know what you think.
#!/bin/bash -e
#######!/bin/bash -ex # The x is to be used for debugging.
#——————————————————————————
#
# 9 may 2016, backuPi.sh
#
#
# Calculates the minimum size of the sd card, and then resizes filesystem
# and partition.
# Subsequently creates an image of the relevant partitions space.
#
#
#
#——————————————————————————
function calcMiB()
{
# Calculate size in MiB, for easier reading.
local partsizeblocks=$1
local KBperblock=$2
local partsizeKiB=$(( ${partsizeblocks} * ${KBperblock} ))
local quotientMiB=”$(( (${partsizeblocks} * ${KBperblock}) / 1024 ))”
local modulusMiB=$(( ($partsizeKiB – ($quotientMiB * 1024))*1000/1024))
local modulusMiB2=”$(( (${partsizeblocks} % ${KBperblock}) / 1024))”
echo “${quotientMiB},${modulusMiB} MiB.”
}
# check which drive is the sd card:
echo “Please select the drive you want to format and write an image to.”
echo “The following filesystems have been found:”
lsblk
read -e -p “Which blockdevice: ” -i “sdc” myblkdev
read -e -p “Which partition do you want to shrink: ” -i “2” targetpartnr
targetpart=”${myblkdev}${targetpartnr}”
# Unmount directories, otherwise online shrinking from resize2fs would be
# required but this throws an error.
if grep -s “${myblkdev}” /proc/mounts
then
echo “Start unmounting partitions”
sudo umount -v “/dev/${myblkdev}”? # Questionmark is wildcard.
fi
# Check the filesystem/partition.
sudo e2fsck -fy “/dev/${targetpart}”
myblockcount=$(sudo tune2fs -l “/dev/${targetpart}” | grep ‘Block count’ | awk ‘{print $3}’)
myfreeblocks=$(sudo tune2fs -l “/dev/${targetpart}” | grep ‘Free blocks’ | awk ‘{print $3}’)
myblocksize=$(sudo tune2fs -l “/dev/${targetpart}” | grep ‘Block size’ | awk ‘{print $3}’)
mysectorsize=$(sudo sfdisk -l “/dev/${myblkdev}” | grep Units | awk ‘{print $8}’)
mystartsector=$(sudo fdisk -l “/dev/${myblkdev}” | grep “${targetpart}” | awk ‘{print $2}’)
# Calculate the smallest partition size, in blocks.
myusedblocks=$(( $myblockcount – $myfreeblocks ))
# Calculate target partion size, adding a bit of margin, about 8%.
mytargetblocks=$(( $myusedblocks + ($myusedblocks * 2 / 25) ))
# Calculate KiB per block to aid further calculation in KiB’s:
if (( “${myblocksize}” >= “1024” ))
then
KBperblock=$(( $myblocksize/1024 ))
else
echo “Blocksize is awkward: ${myblocksize}. Not sure what to do, stopping.”
exit
fi
# Round up new part size to multiple of blocksize to facilitate creation.
mynewpartsize=$(( (($mytargetblocks + $KBperblock-1) / $KBperblock) * $KBperblock ))
# Calculate and print the existing data and target partition size.
echo “”
echo “The size of the data on partion /dev/${targetpart} is \
$( calcMiB ${myusedblocks} ${KBperblock} )”
echo “”
echo “The new size of the data on partion /dev/${targetpart} will be \
$( calcMiB ${mytargetblocks} ${KBperblock} )”
echo “”
# Calculate multiplier from sector size to block size
sectorsperblock=$(( $myblocksize/$mysectorsize ))
# Calculate end point in sectors, that is what fdisk requires.
mynewendpoint=$(( $mystartsector + ($mynewpartsize * $sectorsperblock) ))
# Start execution:
# Resize the filesystem, values in 1024 bytes, see the “K” at the end.
# Example, if blocksize was 4096, nr of blocks x 4 is the resize value.
sudo resize2fs -fp “/dev/${targetpart}” $(( $mynewpartsize * $KBperblock ))K
# Resize partion, to make matters complicated values are in sector sizes.
# NB, the -s switch does not work, putting Yes after the command is the work around.
sudo parted “/dev/${myblkdev}” unit s resizepart “${targetpartnr}” “${mynewendpoint}” yes
sync
# Mounting the drives does not work: error looking up object with path ….
#udisksctl mount -p block_devices/sdc1
#udisksctl mount -p block_devices/sdc2
#udisksctl mount -b /dev/sdc1
#udisksctl mount -b /dev/sdc2
# Backup resized image
read -e -p “Backup the resized image? [Y/N] ” -i “Y” backupchoice
if [[ “${backupchoice}” =~ ^([yY][eE][sS]|[yY])$ ]]
then
mkdir -p ~/backups
read -e -p “Filename :” -i “$(date +%g%m%d)-raspbianbackup.img” Pibackupname
sudo dd if=”/dev/${myblkdev}” | pv | sudo dd of=~/backups/”${Pibackupname}” bs=512 count=”${mynewendpoint}”
echo “Backup succesfull.”
fi
exit
Wow, great work! I have yet to test it, but I’ll be sure to do so soon. Thanks for your contribution, it’s much appreciated.
Hi abracadabricx,
Thanks for sharing this. I’m a noob to linux and I’m not quite sure how to use this script. I tried to typing the commands one after other and it didn’t work. Highly appreciated if you can explain how can I use your script. Thanks!
Cheers,
Anton
Hi abracadabricx,
Can you please explain how can I use your script ? I’m quite new to Linux and Raspberry Pi world. Appreciated if you can advise how can I execute your script. Many Thanks!
The latest version of Raspberry pi OS has a built in software that is very simple to use. It does a exact copy of the SD card. You need a USB card reader with a new empty SD card. Plug this into the usb port of Raspberry pi. And then copy using the software to make copy of the SD card you are booting from …
Can an SD card be programmed to cause a Raspberry Pi/Retropi to boot up and be an Amiga 1200/030, only, to the user?
Hi Chuck,
Thank you for visiting my site. In regards to your question, I really can’t say. It’s not something I tried.
Sorry.
God Bless You!!!! I have been working for over a week to shrink a 64 GB image to a 32 GB card for our big Pi rollout because we found cheaper Pi kits but they used 32 GB cards. I had put a great deal of effort in this image with overlayfs and other optimizations, and to be honest there was no way I was going to remember every optimization I had done to achieve perfection in this 64 GB card. I had given up hope and ordered a lot of 64 GB cards to switch out, but I then stumbled on your page and Option #3 worked perfectly! None of the other options I had tried up until this point worked I suppose because of the overlayfs and other changes that we made to boot.
I know this is an old post, but I just wanted to let you know that your post is still making a difference well into 2021! Thanks again!