Full disk backup on the Raspberry Pi

RaspberryPiOne of the most important thing on the pi is to have decent backups, since our root is on an untrusted sd-card there will always be the risk of that corrupted filesystem.
Over on raspberrypi.org I found a script that fits my needs and uses dd to make a copy of the sd-card and stores that on my NFS (FreeNas) Server that runs zfs raid over multiple disk.
Also doing some test how the pi runs if the root is completely on nfs..(more on that later.)

I stored the backup script on my nfs share that is mounted to /mnt
Backups are stored in /mnt/Pi-backups
Script and logs are in /mnt/scripts
Backup script runs twice a day and the backups for the last 7 days are stored.
Here’s the script.(/mnt/scripts/backup.sh)

#!/bin/bash

# Setting up backup directories
SUBDIR=Pi_backups
DIR=/mnt/$SUBDIR

# Setting up echo fonts
red=’\e[0;31m’
green=’\e[0;32m’
cyan=’\e[0;36m’
yellow=’\e[1;33m’
purple=’\e[0;35m’
NC=’\e[0m’ #No Color
bold=`tput bold`
normal=`tput sgr0`

#Screen clear
clear

echo -e “${green}${bold}Starting RaspberryPI backup process!${NC}${normal}”
echo “”
# First check if pv package is installed, if not, install it first
PACKAGESTATUS=`dpkg -s pv | grep Status`;

if [[ $PACKAGESTATUS == S* ]]
then
echo -e “${cyan}${bold}Package ‘pv’ is installed${NC}${normal}”
echo “”
else
echo -e “${yellow}${bold}Package ‘pv’ is NOT installed${NC}${normal}”
echo -e “${yellow}${bold}Installing package ‘pv’ + ‘pv dialog’. Please wait…${NC}${normal}”
echo “”
sudo apt-get -y install pv && sudo apt-get -y install pv dialog
fi

# Check if backup directory exists
if [ ! -d “$DIR” ];
then
echo -e “${yellow}${bold}Backup directory $DIR doesn’t exist, creating it now!${NC}${normal}”
sudo mkdir $DIR

fi

# Create a filename with datestamp for our current backup (without .img suffix)
OFILE=”$DIR/backup_$(date +%Y%m%d_%H%M%S)”

# Create final filename, with suffix
OFILEFINAL=$OFILE.img

# First sync disks
sync; sync

# Shut down some services before starting backup process
echo “”
echo -e “${purple}${bold}Stopping services before backup${NC}${normal}”
sudo pkill deluged
sudo pkill deluge-web
sudo service deluge-daemon stop
sudo service noip stop
sudo service cron stop
sudo service proftpd stop
sudo service webmin stop
sudo service xrdp stop

# Begin the backup process, should take about 45 minutes hour from 8Gb SD card to NFS
echo “”
echo -e “${green}${bold}Backing up SD card to img file on NFS${NC}${normal}”
SDSIZE=`sudo blockdev –getsize64 /dev/mmcblk0`;
sudo pv -tpreb /dev/mmcblk0 -s $SDSIZE | dd of=$OFILE bs=1M conv=sync,noerror iflag=fullblock

# Wait for DD to finish and catch result
RESULT=$?

# Start services again that where shutdown before backup process
echo “”
echo -e “${purple}${bold}Starting the stopped services${NC}${normal}”
sudo service deluge-daemon start
sudo deluged
sudo deluge-web
sudo service noip start
sudo service cron start
sudo service proftpd start
sudo service webmin start
sudo service xrdp start

# If command has completed successfully, if not, delete created files
if [ $RESULT = 0 ];
then
sudo mv $OFILE $OFILEFINAL
echo “”
echo -e “${green}${bold}RaspberryPI backup process completed! FILE: $OFILEFINAL${NC}${normal}”
echo -e “${yellow}Removing backups older than 7 days${NC}”
sudo find $DIR -maxdepth 1 -name “*.img” -mtime +7 -exec rm {} \;
echo -e “${cyan}If any backups older than 7 days were found, they were deleted${NC}”
exit 0
# Else remove attempted backup file
else
echo “”
echo -e “${red}${bold}Backup failed!${NC}${normal}”
sudo rm -f $OFILE
echo “”
echo -e “${purple}Last backups on NFS:${NC}”
sudo find $DIR -maxdepth 1 -name “*.img” -exec ls {} \;
echo “”
echo -e “${red}${bold}RaspberryPI backup process failed!${NC}${normal}”
exit 1
fi

Make the script executable:

chmod +x /mnt/scripts/backup.sh

Add it to your crontab so it runs twice a day:

crontab -e

And add the following line:

0 4/16 * * * /mnt/scripts/backup.sh > /mnt/scripts/cron.log 2>&1

That’s all for today, Let’s make a test backup by running:

/mnt/scripts/backup.sh

 

Leave a Reply

Your email address will not be published. Required fields are marked *

*