Code Done Right!

Backup

It is always good to make backups. I learned that the hard way. If you want to make a complete backup of a drive (including an SD card), you can take care of that with a single command.

Cloning an SD card is a very good way to backup your Raspberry Pi server! It can be a lifesaver if something goes wrong or your card simply dies on you… Which may happen when a sudden loss of power occurs.

Making a backup using commands

First, you need to locate the disk you want to backup. To do that check this tutorial, locate the disk and come back here.

Now that you know which disk letter you need to specify, open terminal in the folder where you want to store your backup and issue the following command

sudo dd if=/dev/sdX of=backup.img bs=4M conv=noerror status=progress && zip backup.zip backup.img && sudo rm backup.img

CAUTION! you need to change the line, so that it reflects your drive. Simply modify if=/dev/sdX by changing X to the proper letter of your drive.

Once the command is finished, you will find a file named backup.zip in your current folder. If you don’t know where you are, just type pwd

dd command breakdown

  • if specifies the input, like a disk for example
  • of specifies the output, in this case a file where dd is supposed to write the backup
  • bs is optional, but it changes the block size, 4M will force dd to use 4 mb chunks, which will speed up the process, in case of a hard drive you can use 64M
  • conv=noerror tells dd to ignore errors and carry on the operation
  • status=progress shows the progress, otherwise you will see no output and you will wonder if anything is actually happening

Breakdown of the rest

  • && tells bash to continue only if previous operation was a success
  • zip zips, archive file name goes first, then files to be archived
  • rm removes a file, why keep a bloated .img file if you have a .zip

Restoring a backup using commands

Now that you have a backup file, you need to learn how to get it restored. This can be taken care of with a single command as well, and as previously, you need to specify the right letter of the drive that you want to write to.

CAUTION dd will not ask if you are sure that you want to overwrite the disk. It assumes that you know what you are doing. If you get the letter wrong you may end up erasing something you do not want to. You have been warned. Make sure you identified the correct drive! The dd command stands for disk dump, but it is also called disk destroyer, be careful.

Again, open a terminal window in the folder with the backup file and issue the following command

unzip backup.zip && sudo dd if=backup.img of=/dev/sdX bs=4M conv=noerror status=progress && sudo rm backup.img

CAUTION you need to change the line so that it reflects your drive. Simply modify of=/dev/sdX by changing X to the proper letter of your drive.

Once the command is finished your backup will have been written to your drive successfully.

Making a backup using script

It is also possible to utilize bash script if you are frequently making backups and want more power and flexibility while making them. Put the following code in a file my_backup.sh in your script folder, if you have been following my guides your script folder should be /var/zzz_script/

#!/bin/bash
set -e

clear

DATE="$(which date)"
TIMESTAMP=`$DATE '+%Y.%m.%d'`

export WORK_DIR=`pwd`

echo ""
echo "Linux Backup and Restore Helper"

echo ""
echo "Hello $USER, Please follow on-screen instructions"
echo ""
echo "This script creates and restores backups of a drive, sudo is required"
echo "To find out drive letters run 'sudo fdisk -l' and identify your drive"
echo "Script works from current working directory."
echo ""
echo "Please select function..."
echo "b: Make a backup"
echo "r: Restore a backup"
echo "q: quit"
echo ""

read -p "What would you like to do (b/r/q): " PART

if [ $PART = b ]; then

    echo ""
    echo "This part will make a backup." 
    echo "Which device would you like to clone?"
    
    read -p "Please provide the letter (sdX): " DRIVE_B
    
    echo ""
    echo "Cloning /dev/sd${DRIVE_B}"
    echo ""
    echo "Output file name structure is NAME_${TIMESTAMP}.zip"
    
    read -p "Please specify NAME part: " NAMEB
    
    echo ""
    echo "Output file will be named ${NAMEB}_${TIMESTAMP}.zip"
    echo ""
    echo "This will take a while. Please wait... "
    echo ""

    sudo dd if=/dev/sd${DRIVE_B} of=${NAMEB}_${TIMESTAMP}.img bs=4M conv=noerror status=progress

    echo ""
    echo "Compressing ${NAMEB}_${TIMESTAMP}.img, please wait..."
    
    zip ${NAMEB}_$TIMESTAMP.zip ${NAMEB}_${TIMESTAMP}.img

    echo ""
    echo "Removing ${NAMEB}_${TIMESTAMP}.img"
    
    sudo rm ${NAMEB}_${TIMESTAMP}.img

    SIZE="$(du -h ${NAMEB}_${TIMESTAMP}.zip | awk '{ print $1 }')"

    echo ""
    echo "The file ${NAMEB}_${TIMESTAMP}.zip is about ${SIZE}."
    echo "Full file path is ${WORK_DIR}/${NAMEB}_{$TIMESTAMP}.zip"

elif [ $PART = r ]; then

    echo ""
    echo "This part will restore a backup."
    echo ""
    echo "Script looks for input file with the following pattern NAME_YYYY.MM.DD.zip"
    echo ""
    echo "To which device would you like to write?"
    
    read -p "Please provide the letter (sdX): " DRIVE_R
    
    echo ""
    echo "Which file you want to restore?"
    
    read -p "Please specify NAME part of the name: " NAMER
    read -p "Please specify YYYY part of the name: " YEAR
    read -p "Please specify MM   part of the name: " MONTH
    read -p "Please specify DD   part of the name: " DAY

    echo ""
    echo "Unzipping ${NAMER}_${YEAR}.${MONTH}.${DAY}.zip" 
    echo "This will take a while. Please wait..."
    echo ""
    
    unzip ${NAMER}_${YEAR}.${MONTH}.${DAY}.zip

    echo ""
    echo "Writing ${NAMER}_${YEAR}.${MONTH}.${DAY}.img to /dev/sd${DRIVE_R}"
    echo "This will take a while. Please wait..."
    
    sudo dd if=${NAMER}_${YEAR}.${MONTH}.${DAY}.img of=/dev/sd${DRIVE_R} bs=4M conv=noerror status=progress

    echo ""
    echo "Removing ${NAMER}_${YEAR}.${MONTH}.${DAY}.img"
    
    sudo rm ${NAMER}_${YEAR}.${MONTH}.${DAY}.img

    echo ""
    echo "Drive /dev/sd${DRIVE_R} is ready for use"

else

    echo ""

fi

echo ""
echo "Done."

The code does not neet comments as it tells the user exactly what it is going to do on each stage. If you are curious, and you should be as this is foregin code, read echo lines before each command.

In short, the script is divided into two sections, one making a backup, and one restoring it. Additionally it allows for exiting without performing any action and informs the user upon selecting wrong part.

The part making the bakup

  • makes 1:1 copy of the drive and saves it as img file in the folder from which the script was executed
  • zips the img file
  • removes the img file
  • checks the size of the zip file
  • prints the filepath to your new backup
  • names files name_YYYY.MM.DD.zip and name_YYYY.MM.DD.img

The part restoring the backup

  • asks which drive you want to write to
  • asks for the file name
  • unzips the archive
  • writes img file to the specified drive
  • removes the img file

Why zip the file? If your drive is 32GB the dump will take exactly that much space, however, if only 10GB of that drive is used the zip will compress the unsused space, saving space on the drive where you store backups.

Time needed for the script to run depends on the speed of your device.

CAUTION! The owner of the backup file will be root. However, since you need root privileges to use dd anyways this will not be an issue. Just making a note.

Making an alias for ease of use

Now here is best part. The output will be placed in the folder from which the script is executed. This means that you can navigate to the folder where you keep your backups, run the script and the backup will be placed there, with current date in the name. You can run the script manually every time or you can make an alias.

To make a permanent alias to the script check out this page. I have chosen my_backup as the name for my alias.

If you just want to make a temporary alias to see how it works, use the following command. It will be retained in memory until you reboot.

alias my_backup="/var/zzz_script/dump.sh"

Now when you type my_backup in your terminal the my_backup.sh script will be executed in the folder where you are currently in terminal.

Hot backup

Unfortunately hot backups, made while server is up, are not advisable due to the fact that system might write to a disk while the backup is under way. You can find some lengthy bash scripts that will attempt to do so, but if you are a newbie I would advise to just take down the server for an hour and perform the backup while it is down. You might get away with one or two consecutive hot backups done this way but down the line you will encounter an unrecoverable error.

Conclusion

Backing up your data is crucial. Unless you want to set up everything multiple times just make a backup before a major upgrade and afterwards, if successful. Depending on the drive size this might be a long process, however, it will still take less time than setting up a server that you have been using and growing for a year or more. dd can run in a background terminal window while you surf the web or watch Rick & Morty.

CAUTION! Word of caution, test out the backup process before you realize that your backups are worthless. You can use a pendrive or an SD card that is fairly small, like 2GB, so that the process will be fast. Put some files on the drive, make a backup, wipe the drive, restore it and see if it worked.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.