6
\$\begingroup\$

This is the backup script itself. Make it executable and place it somewhere in your path:

#!/bin/bash
# Debug:
# set -x
# export PS4='$LINENO:'
TAR_BACKUP_VERSION="1.01"
# Stop on errors:
set -e
set -o pipefail
# Run as root:
if [ "$EUID" -ne 0 ]
 then echo "We need root (administrator) privileges to run this..."
 sudo bash -c "${0}"
 echo ""
 read -p "Press [enter] to terminate. " asomevar
 exit
fi
# Functions:
function finish {
 rm -rf "${PART_LOCATION}"
}
store_partition_layout () {
 if [ "${BACKUP_TYPE,,}" == "full" ] && [ ! -z "${PART_LOCATION}" ]; then
# Check if the directory/file already exists: 
 if [[ -e ${PART_LOCATION} ]] ; then
 echo "Error! ${PART_LOCATION} already exists. Please rename or remove it."
 exit 1
 fi 
# Store the partition layout:
 trap finish EXIT
 mkdir "${PART_LOCATION}"
 PIPE_TARGET="${PART_LOCATION}/partition-layout.txt"
 echo "##################################################################" >| "${PIPE_TARGET}"
 echo "### Partitionals via: lsblk -o name,mountpoint,label,size,uuid ###" >> "${PIPE_TARGET}"
 echo "##################################################################" >> "${PIPE_TARGET}"
 lsblk -o name,mountpoint,label,size,uuid >> "${PIPE_TARGET}"
 echo "" >> "${PIPE_TARGET}"
 echo "" >> "${PIPE_TARGET}"
 echo "##################################################################" >> "${PIPE_TARGET}"
 echo "### Partitionals via: fdisk -l ###" >> "${PIPE_TARGET}"
 echo "##################################################################" >> "${PIPE_TARGET}"
 fdisk -l >> "${PIPE_TARGET}"
# echo "Created text file with new partition layout: ${PIPE_TARGET}"
 STORE_PARTITION_LAYOUT_OUTPUT+="Created text file with new partition layout: ${PIPE_TARGET} in the archieve"
 STORE_PARTITION_LAYOUT_OUTPUT+=$'\n'
 if [ ! -z "${BOOT_SECTORS}" ]; then
 for BOOTSEC in ${BOOT_SECTORS}
 do
 PNAME="${BOOTSEC##*/}"
 BSNAME="${PART_LOCATION}/${PNAME}_boot-sector.bak"
 dd if=${BOOTSEC} of=${BSNAME} bs=512 count=1 status=none
# echo "Created backup of boot sector from ${BOOTSEC} as ${BSNAME}"
 STORE_PARTITION_LAYOUT_OUTPUT+="Created backup of boot sector from ${BOOTSEC} as ${BSNAME} in the archieve"
 STORE_PARTITION_LAYOUT_OUTPUT+=$'\n' 
 done
 fi
# Store UEFI boot stuff (and NVRAM partition), if wanted:
 if [ "${STORE_UEFI_BOOT,,}" == "yes" ]; then
 efibootmgr -v >| "${PART_LOCATION}/UEFI_boot-entries.txt"
 dd if=/dev/nvram of="${PART_LOCATION}/nvram.bin"
 fi
 fi
}
output_time_it_took () {
 END=$(date +%s)
 DIFF=$(( $END - $START ))
 printf "Operation took: %02d:%02d:%02d (hours:minutes:seconds)" $(($DIFF/3600)) $(($DIFF%3600/60)) $(($DIFF%60))
 echo ""
}
suspend_to_disk_yes_no () {
 if [ -z "${1}" ]
 then
 OPERATION="backup"
 else
 OPERATION="${1}"
 fi
 echo ""
 echo "Suspend to computer to disk after ${OPERATION}? [y/n]"
 echo ""
 while true; do
 read -p "Please enter y or n: " wtd
 case $wtd in
 [Yy] ) SUSPEND_TO_DISK_AFTERWARDS="1"; break;;
 [Nn] ) SUSPEND_TO_DISK_AFTERWARDS=""; break;;
 * ) echo "Please answer with y or n.";;
 esac
 done
 echo ""
}
perform_backup () {
 FULL_BACKUP_FILENAME="`ls -d ${TAR_BACKUP_BACKUP_LOCATION}`/${BACKUP_FILENAME}"
 suspend_to_disk_yes_no
 START=$(date +%s)
 CUTOFF=$((${#TAR_BACKUP_COMPRESSOR}+4))
 FULL_CHECKSUM_FILENAME="${FULL_BACKUP_FILENAME:0:-${CUTOFF}}${TAR_BACKUP_CHECKSUM_COMMAND}"
# FULL_CHECKSUM_FILENAME="${FULL_BACKUP_FILENAME}.${TAR_BACKUP_CHECKSUM_COMMAND}"
 SNAR_FULL_FILENAME="`ls -d ${TAR_BACKUP_BACKUP_LOCATION}`/${BACKUP_FILENAME:0:-${CUTOFF}}snar"
# Build the exclude list:
 OLDIFS=${IFS}
 EXCLUDE_NE=""
 while IFS= read -r line; do
 if [ ! -z "${line}" ] && [[ $line != //* ]]; then
 EXCLUDE_NE=( "${EXCLUDE_NE[@]}" "--exclude=${line}" )
 fi
 done <<< "${EXCLUDE_THESE}"
 IFS=${OLDIFS}
 EXCLUDE_NE=`echo "${EXCLUDE_NE[@]}"`
 STORE_PARTITION_LAYOUT_OUTPUT=""
 TAR_BACKUP_SOURCES=( "${TAR_BACKUP_SOURCE}" "${PART_LOCATION}" )
 if [ "${1,,}" == "full" ]; then
# Doing a full backup:
 BACKUP_TYPE="1ドル"
 store_partition_layout
 if [ "${REMOVE_SNAR_OF_OLD_FULL_BACKUPS,,}" = "yes" ]; then
 NO_SNAR="yes"
 fi
 else
# Doing a differential backup:
 BACKUP_TYPE="differential"
 OLD_SNAR_FULL_FILENAME="`ls -d ${TAR_BACKUP_BACKUP_LOCATION}`/${LAST_FULL_BACKUP:0:-${CUTOFF}}snar" 
 if [ "${REMOVE_SNAR_OF_DIFFERENTIAL_BACKUPS,,}" = "yes" ]; then
# User does not want to keep the snar file of the differential backup, so put it into /tmp:
 NO_SNAR="yes"
 SNAR_TMPDIR=$(mktemp -d -t snar_of_differntial_backup-XXXXXXXXXX)
 SNAR_FULL_FILENAME="${SNAR_TMPDIR}/${SNAR_FULL_FILENAME##*/}"
 fi
 cp -n "${OLD_SNAR_FULL_FILENAME}" "${SNAR_FULL_FILENAME}"
 fi
 echo "Doing a ${BACKUP_TYPE} backup of ${TAR_BACKUP_SOURCE[@]}"
 tar -cpf - ${TAR_BACKUP_OPTIONS} -g "${SNAR_FULL_FILENAME}" ${EXCLUDE_NE} "${TAR_BACKUP_SOURCES[@]}" \
 | ${TAR_BACKUP_COMPRESSOR} ${TAR_BACKUP_COMPRESSION_LEVEL} \
 | tee >(CHECKSUM=$(mbuffer ${BUFFER_PARAMETERS} | "${TAR_BACKUP_CHECKSUM_COMMAND}" "${TAR_BACKUP_CHECKSUM_PARAM}");echo "${CHECKSUM:0:-1}${BACKUP_FILENAME}" > "${FULL_CHECKSUM_FILENAME}" )\
 | mbuffer ${BUFFER_PARAMETERS} > "${FULL_BACKUP_FILENAME}"
# Get the archive size:
 ARCHIVE_SIZE=`ls -lLh "${FULL_BACKUP_FILENAME}" | cut -f 5-5 -d ' '`
 if [ "${NO_SNAR}" != "yes" ]; then
# Add the checksum of the snar file as well:
 cd "${TAR_BACKUP_BACKUP_LOCATION}"
 eval "${TAR_BACKUP_CHECKSUM_COMMAND} ${TAR_BACKUP_CHECKSUM_PARAM} ${BACKUP_FILENAME:0:-${CUTOFF}}snar >> ${FULL_CHECKSUM_FILENAME}"
 cd - > /dev/null
 else
# Remove old snar files of full backups:
 if [ "${BACKUP_TYPE,,}" == "full" ]; then
 if [ ! -z "${LAST_FULL_BACKUP}" ]; then
 cd "${TAR_BACKUP_BACKUP_LOCATION}" 
 SNAR_TMP=$(mktemp -d -t snar_of_old_full_backup-XXXXXXXXXX)
 for i in ????????-??????_${TAR_BACKUP_NAME}_full-backup.snar; do
 [ -f "$i" ] || break
 if [ "${i}" != "${BACKUP_FILENAME:0:-${CUTOFF}}snar" ]; then
 mv -f "${i}" "${SNAR_TMP}"
 fi
 done 
 cd - > /dev/null
 fi
 fi
 fi
 echo ""
# Output partition layout info:
 if [ ! -z "${STORE_PARTITION_LAYOUT_OUTPUT}" ]; then
 echo "${STORE_PARTITION_LAYOUT_OUTPUT}"
 fi
 echo "Finished doing a ${BACKUP_TYPE} backup."
 echo "Backup name is: ${BACKUP_FILENAME} (${ARCHIVE_SIZE} in size)"
# Execute post-backup command:
 if [ ! -z "${TAR_BACKUP_POST_COMMAND}" ]
 then
 eval ${TAR_BACKUP_POST_COMMAND}
 fi
}
perform_FULL_backup () {
 BACKUP_FILENAME="`date +%Y%m%d-%H%M%S`_${TAR_BACKUP_NAME}_full-backup.tar.${TAR_BACKUP_COMPRESSOR}"
 TAR_BACKUP_COMPRESSION_LEVEL="${TAR_BACKUP_COMPRESSION_LEVEL_FULL}"
 perform_backup "full"
}
perform_DIFFERENTIAL_backup () {
 if [ -z "${LAST_FULL_BACKUP}" ]
 then
 echo "There are no full backups. Can't make a differential backup."
 echo "Make a full backup first!"
 exit 1
 fi
 CUT_END=$((${#TAR_BACKUP_COMPRESSOR}+5))
 BASED_NAME="${LAST_FULL_BACKUP:0:-$CUT_END}"
 BACKUP_FILENAME="`date +%Y%m%d-%H%M%S`_${TAR_BACKUP_NAME}_diff-backup_based_on_${BASED_NAME}.tar.${TAR_BACKUP_COMPRESSOR}"
 TAR_BACKUP_COMPRESSION_LEVEL="${TAR_BACKUP_COMPRESSION_LEVEL_DIFF}"
 perform_backup "diff"
}
VERIFY_backup () {
 suspend_to_disk_yes_no "verify"
 echo "Verifying backup"
 BACKUP_TO_VERIFY=`( cd ${TAR_BACKUP_BACKUP_LOCATION}; zenity --title="Select backup file to verify, the compressed \".tar\"-archieve and not the checksum file:" --file-selection 2> /dev/null )`
 START=$(date +%s)
# Set the type of backup: 
 if [[ ${BACKUP_TO_VERIFY} == *"_diff-backup_based_on"* ]]; then
 BACKUP_TYPE="differential"
 if [ "${REMOVE_SNAR_OF_DIFFERENTIAL_BACKUPS,,}" = "yes" ]; then
 NO_SNAR="yes"
 fi
 else
 BACKUP_TYPE="full"
 if [ "${REMOVE_SNAR_OF_OLD_FULL_BACKUPS,,}" = "yes" ]; then
 NO_SNAR="yes"
 fi
 fi
# SUMFILE_TO_VERIFY="`ls -d "${BACKUP_TO_VERIFY}".*`"
 SUMFILE_TO_VERIFY="`ls -d ${BACKUP_TO_VERIFY}`"
 SUMFILE_TO_VERIFY=${SUMFILE_TO_VERIFY%%.*}
 
 SUMCOMMAND="${SUMFILE_TO_VERIFY:$((${#BACKUP_TO_VERIFY}+1))}"
 DECOMPRESS_COMMAND="${BACKUP_TO_VERIFY##*.} ${TAR_BACKUP_DECOMPRESS_OPTION}"
 echo ""
 echo "Testing checksum and archieve integrity"
 TMPFILE=`mktemp /tmp/chksumout.XXXXXXXXXX`
 mbuffer ${BUFFER_PARAMETERS} -i "${BACKUP_TO_VERIFY}" \
 | tee >(CHECKSUM=`"${TAR_BACKUP_CHECKSUM_COMMAND}" "${TAR_BACKUP_CHECKSUM_PARAM}"`;echo "${CHECKSUM}" >| ${TMPFILE}) \
 | eval "${DECOMPRESS_COMMAND}" | tar tf - && export ARCPASS="OK" || export ARCPASS="FAIL"
 CHKCALC=`cat "${TMPFILE}"`
 CHKCALC="${CHKCALC%%\ *}"
 CHKFILE=`cat "${SUMFILE_TO_VERIFY}.${TAR_BACKUP_CHECKSUM_COMMAND}"`
 readarray -t CHECKSUM_ARRAY <<<"${CHKFILE}"
 ARCHIEVE_CHECKSUM="${CHECKSUM_ARRAY[0]%%\ *}"
# echo "calculated ac: $CHKCALC"
# echo "stored archic: $ARCHIEVE_CHECKSUM"
 if [ "${NO_SNAR}" != "yes" ]; then
 SNAR_CHECKSUM="${CHECKSUM_ARRAY[1]%%\ *}"
 CHKCALCSNAR=`"${TAR_BACKUP_CHECKSUM_COMMAND}" "${TAR_BACKUP_CHECKSUM_PARAM}" "${BACKUP_TO_VERIFY%%.*}.snar"`
 CHKCALCSNAR="${CHKCALCSNAR%%\ *}"
# echo "calculated sc: $CHKCALCSNAR"
# echo "stored snarck: $SNAR_CHECKSUM"
 fi
 if [ "${CHKCALC}" == "${ARCHIEVE_CHECKSUM}" ]; then
 CHKPASS="OK"
 else
 CHKPASS="FAIL"
 CORRUPTED="YES"
 fi
 rm -f "${TMPFILE}"
 echo ""
 echo "Checksum test: ${CHKPASS}"
 echo "Archieve test: ${ARCPASS}"
 if [ "${ARCPASS}" != "OK" ]; then
 CORRUPTED="YES"
 fi
 if [ ! -z "${CORRUPTED}" ]; then
 echo "The archieve has probably been corrupted!"
 fi
 if [ "${NO_SNAR}" != "yes" ]; then
 if [ "${CHKCALCSNAR}" == "${SNAR_CHECKSUM}" ]; then
 echo "snar file test: OK"
 else
 echo "snar file test: FAIL"
 echo "The snar file has probably been corrupted!" 
 fi
 fi
 echo ""
}
PRINT_HELP () {
 HELP_STRING='
Instructions for restoring your system from a backup:
First of all a word of warning: If you do not know what you 
are doing, you can easily erase all your data and seriously 
fuck-up your system by mistake! You can do so even when you 
know what you are doing, by being careless.
First, make sure to have everything backed up!
Your Linux system should let you click on the archives and 
view their contents in a GUI. This can also be used to 
extract only certain folders and files. As the archives are 
usually big, this can take a lot of time.
You may consider the alternative of simply mounting the 
archives to a folder. You can then treat the folder (and its 
content) normally, read-only, of course. For instance, you 
could run the "find" command to look for something 
particular.
In order to mount an archive to a folder, use the 
"archivemount" command (you may have to install it first). 
The usage is straightforward. You create a directory where 
you want the contents of the archive to appear virtually and 
then:
archivemount your-archive.tar.xz your-directory
Don not forget to "unmout" the directory afterwards.
When extracting a full backup for restoration, you can 
choose two methods.
Method 1: extract everything into a directory and afterwards 
move the contents to the right locations (which may need to 
be mounted to the correct folders).
Method 2: Go to your empty root partition and mount all 
partitions needed to the correct folders (/boot, for 
instance). Now extract everything, excluding stuff you do
not want to extract (/boot/efi for instance). Note that the
"--numeric-owner" flag is important when restoring from
live-CD/DVD:
cd /
DECOMPRESS_COMMAND -d -c your-full-archive-name.tar.compressor | tar xvpf - --exclude=/boot/efi --numeric-owner
Note that the "DECOMPRESS_COMMAND" is the compressor (named 
in the extension as well). You start with the full backup, 
of course. Then you add the latest differential (if that
is the newest backup):
DECOMPRESS_COMMAND -d -c your-latest-differential-backup-name.tar.compressor | tar xvpf - -g /dev/zero --exclude=/boot/efi --numeric-owner
You can find the layout of your partitions in each full(!) 
backup under the folder named by the PART_LOCATION variable 
in your config file (/partition-layout by default).
There you can see the partitions, the partition types and 
sizes (and their names). You can restore them automatically 
or manually via "fdisk". Read up on how to do so properly by 
searching for something like "how to use fdisk to manage 
partitions on linux".
This is only needed, if you are looking to install to a new 
system or your old system went completely blank, of course.
If you added the proper locations of your boot partitions to 
the BOOT_SECTORS variable, you will also find a backup of 
those boot (or root/MBR) sectors there.
An example for restoring (Warning: this can kill your 
system, when not knowing what you are doing!), after having 
extracted the folder named in PART_LOCATION from your full 
backup archive:
Suppose you want to restore your MBR and the drive was and 
still is /dev/sda. Suppose that you did not change anything 
and thus HAVE IDENTICALLY SIZED PARTITIONS and you are in 
the folder of the partition backup:
dd if=sda_boot-sector.bak of=/dev/sda bs=512 count=1
This will restore the entire 512 bytes of your MBR.
Suppose you want to restore the boot block of partition 
/dev/sda3, but you have changed the size of that partition 
on your new system:
dd if=sda3_boot-sector.bak of=/dev/sda3 bs=446 count=1
Here we restore the boot-sector to a partition WITH A 
DIFFERENT SIZE. If they have the same size, you can use the 
code from above (with the 512 bytes).
For those having UEFI systems:
If you added (and mounted) the EFI partition, when you made 
a backup, you can find it in there as well (/boot/efi). This 
will then contain the backup of that FAT-partition with the 
UEFI compliant boot loaders.
If you set the STORE_UEFI_BOOT to "yes", then you will also 
find the UEFI boot entries in the PART_LOCATION folder as 
"UEFI_boot-entries.txt", while "nvram.bin" will contain a 
backup of your NVRAM.
"efibootmgr" can be used to manipulate (restore) the boot 
entries, "efivar" for all the other variables (normally you 
should not need this).
I hope that this has been somewhat helpful. You can find 
more in-depth help on the Internet.
'
 echo "${HELP_STRING}" | more
}
check_prog_existance () {
 command -v "${1}" >/dev/null 2>&1 || { echo >&2 "I require \"${1}\" but it is not installed. Aborting."; exit 1; }
}
# Read in the configuration (source it):
source "${HOME}/.config/tar_backup_config.sh"
# Check for programms needed:
check_prog_existance "tr"
check_prog_existance "dd"
check_prog_existance "cut"
check_prog_existance "tar"
check_prog_existance "tee"
check_prog_existance "sed"
check_prog_existance "fdisk"
check_prog_existance "lsblk"
check_prog_existance "zenity"
check_prog_existance "printf"
check_prog_existance "mbuffer"
check_prog_existance "${TAR_BACKUP_COMPRESSOR}"
check_prog_existance "${TAR_BACKUP_CHECKSUM_COMMAND}"
if [ "${STORE_UEFI_BOOT,,}" == "yes" ]; then
 check_prog_existance "efibootmgr"
fi
#echo ""
# Looking for a bug here that causes a freeze. Pre-running possibly culprits:
echo "test" | mbuffer -q > /dev/null
echo "test" | ${TAR_BACKUP_CHECKSUM_COMMAND} > /dev/null
# Execute pre-backup command:
if [ ! -z "${TAR_BACKUP_PRE_COMMAND}" ]
then
 eval ${TAR_BACKUP_PRE_COMMAND}
fi
# Get the last full and differential backup names:
LAST_BACKUP=`( cd ${TAR_BACKUP_BACKUP_LOCATION}; ls ) | grep -v 'sum' | grep -e '^[0-9]\{8\}-[0-9]\{6\}_'${TAR_BACKUP_NAME}'_\(full\|diff\)-backup\(\?\:_based_on\)\?.*\.tar\..*' | tail -1 || true`
LAST_FULL_BACKUP=`( cd ${TAR_BACKUP_BACKUP_LOCATION}; ls ) | grep -v 'sum' | grep -e '^[0-9]\{8\}-[0-9]\{6\}_'${TAR_BACKUP_NAME}'_full-backup\.tar\..*' | tail -1 || true`
LAST_DIFF_BACKUP=`( cd ${TAR_BACKUP_BACKUP_LOCATION}; ls ) | grep -v 'sum' | grep -e '^[0-9]\{8\}-[0-9]\{6\}_'${TAR_BACKUP_NAME}'_diff-backup_based_on.*\.tar\..*' | tail -1 || true`
if [ -z "${LAST_FULL_BACKUP}" ]
then
 echo "No backups (no full backup) found."
 LAST_DIFF_BACKUP=""
 LAST_BACKUP=""
else
 echo "Last full backup: ${LAST_FULL_BACKUP}"
 if [ -z "${LAST_DIFF_BACKUP}" ]
 then
 echo "No differential backups."
 else
 echo "Last differential backup: ${LAST_DIFF_BACKUP}"
 fi
 LAST_BACKUP_AGE="${LAST_BACKUP:0:8}"
 LAST_SECONDS=`date -d $LAST_BACKUP_AGE '+%s'`
 AGE=$(( $(date +%s) - $LAST_SECONDS ))
 printf "Last backup is %d days old." $(($AGE/86400))
fi
# Ask the user what to do:
echo ""
echo ""
echo "tar_backup.sh V${TAR_BACKUP_VERSION}"
echo "==================="
echo "Perform [f]ull, [d]ifferencial, [v]erify a backup or [p]rint help for restoring?"
echo ""
while true; do
 read -p "Please enter f, d, v or p: " wtd
 case $wtd in
 [Ff] ) perform_FULL_backup; break;;
 [Dd] ) perform_DIFFERENTIAL_backup; break;;
 [Vv] ) VERIFY_backup; break;;
 [Pp] ) PRINT_HELP; break;;
 * ) echo "Please answer f, d or v.";;
 esac
done
output_time_it_took
# Suspend to disk, if user wishes so:
if [ ! -z "${SUSPEND_TO_DISK_AFTERWARDS}" ]
then
 echo "Suspending system to disk in ${TAR_BACKUP_SUSPEND_WAIT} seconds..."
 sleep ${TAR_BACKUP_SUSPEND_WAIT}
 
 
 eval ${TAR_BACKUP_SUSPEND_COMMAND}
fi
exit 0

The configuration file. Edit this to your liking. Place it in $HOME/.config/tar_backup_config.sh. Make sure that you set the path to the backup output folder and add that to the excluded folders:

# This is the configuration file of the "tar_backup" shell script.
# It is usually located in "~/.config/tar_backup_config.sh"
echo ""
# Backup location (directory):
# make sure that this is within the excluded directories!!!!!!!!!!!!!
#TAR_BACKUP_BACKUP_LOCATION="/home/*/tmp/backups"
TAR_BACKUP_BACKUP_LOCATION="/media/*/*"
echo "The backups will be written to: ${TAR_BACKUP_BACKUP_LOCATION}"
# My name for backups (keep this short!):
#
# This will then become something like this:
# date-time_name_type-backup.tar.your_compressor
# Example: 20190920-175933_linux_full-backup.tar.xz
# or: 20190920-181103_linux_diff-backup_based_on_20190920-175933_linux_full-backup.tar.xz
TAR_BACKUP_NAME="myname"
# What to backup:
#
# Make sure to add all the mouted file systems, as we are using the "--one-file-system"
# option with tar! Make sure to mount them in the TAR_BACKUP_PRE_COMMAND.
# Typically /boot is on a different filesystem. If you are on a UEFI system and want
# your UEFI variables backed up as well, add /boot/efi (and mount it).
# Examples:
# "/" = when you got it all on one partition
# "/ /boot /boot/efi /home" = backup the root partition, the boot partition, the UEFI vars and your home (when all have their own seperate partitions)
# ${HOME} = only your home directory
# Note: no trailing slash!
# Note #2: These have precedence over the excluded folders.
# Hence, if you wish to exclude /var/tmp, but add /var/tmp/important - add it here.
TAR_BACKUP_SOURCE="/"
echo "This will be backed up: ${TAR_BACKUP_SOURCE}"
# These directories or files are excluded.
# directory/* will exclude the contents, but store the empty directory in the archive.
# Thus, */.cache/* will exclude all .cache directory's contents, while keeping the
# directories. /lost+found will exclude both directory and contents from the backup.
# Only C++ style comments starting with double slashes (//) are allowed.
# Emtpy lines are allowed as well.
EXCLUDE_THESE='
// These will be excluded, while the archive will contain the empty directories:
/dev/*
/proc/*
/sys/*
/mnt/*
/media/*
/run/*
/var/run/*
/var/log/*
/var/lock/*
/home/*/.gvfs/*
/home/*/.thumbnails/*
/home/*/.local/share/Trash/*
/home/*/.local/share/Steam/*
// Exclude all cache directories, while keeping the empty directories:
*/.cache/*
*/.Cache/*
*/caches/*
*/Caches/*
*/cache/*
*/Cache/*
// Exclude all tmp directories, while keeping the empty directories.
// Note: This already excludes /tmp and /var/tmp
*/tmp/*
// Exclude the lost+found folder in root and do not store the empty directory:
/lost+found
'
# Backup the partition layout and boot sector(s) (only on full backups).
# Leave this empty ="", if you don't want this.
# Make sure that this is NOT within the excluded directores!
# PART_LOCATION="/partition-layout"
PART_LOCATION="/partition-layout"
# List the partitions for which to backup the boot(/root) sector(s) here.
# If you don't want this, leave it empty ="".
# BOOT_SECTORS="/dev/sda1 /dev/sda3"
BOOT_SECTORS="/dev/sda /dev/sda1"
# If you wish to add a dump of your UEFI boot settings (note that you need
# to have an UEFI system for this) you can set this to "yes".
# Note that for convenience this will also store a backup of the NVRAM
# partition (both very small)!
STORE_UEFI_BOOT="yes"
# Set the program used for compression:
#
# xz = high compression, slow (with "-9 -e" it can be impossibly slow)
# bzip2 = slightly less good
# lzip = a lot faster
# gzip = bad crompression ratio
#
#TAR_BACKUP_COMPRESSOR="xz"
TAR_BACKUP_COMPRESSOR="plzip"
# Option for decompression to stdout:
TAR_BACKUP_DECOMPRESS_OPTION="-d -c"
# Set the compression level:
# 0-9, where 0 ist the fastest (bad compression ratio)
# and 9 is the slowest (best compression, most memory usage).
# Adding "-e" (extreme) to some compressors (xz) will increase
# compression ratio, but it may double compression time.
# Adding "-T X" will use X threads (xz), where "-T 0"
# defaults to the number of available cores.
#TAR_BACKUP_COMPRESSION_LEVEL="-T 0 -9 -e"
TAR_BACKUP_COMPRESSION_LEVEL_FULL="-9"
TAR_BACKUP_COMPRESSION_LEVEL_DIFF="-9"
echo "The command for compression will be: \"${TAR_BACKUP_COMPRESSOR} ${TAR_BACKUP_COMPRESSION_LEVEL_FULL}\" [full backup] or \"${TAR_BACKUP_COMPRESSOR} ${TAR_BACKUP_COMPRESSION_LEVEL_DIFF}\" [differential]"
# We don't need the snar files for restoring backups.
# Hence, snar files of old full backups can be deleted:
REMOVE_SNAR_OF_OLD_FULL_BACKUPS="yes"
# We don't need the snar files for restoring backups.
# Hence, snar files from differential backups can be deleted:
REMOVE_SNAR_OF_DIFFERENTIAL_BACKUPS="yes"
# Checksum program:
# Example: "sha512sum -b"
TAR_BACKUP_CHECKSUM_COMMAND="sha512sum"
# Parameters:
TAR_BACKUP_CHECKSUM_PARAM="-b"
# buffer parameters:
BUFFER_PARAMETERS="-b 5 -m 40m -p 75"
# Seconds to wait, before suspending to disk (if wanted):
TAR_BACKUP_SUSPEND_WAIT="30"
# Command to execute for suspending to disk:
# Example: "systemctl hibernate"
TAR_BACKUP_SUSPEND_COMMAND="systemctl hibernate"
# Commands to execute before and after backup
# (for mounting devices and such):
TAR_BACKUP_PRE_COMMAND="echo '' || true"
TAR_BACKUP_POST_COMMAND="echo '' || true"
# tar options (except for some weird exclude szenarios you should
# not have change these:
# --one-file-system --exclude-backups -v
TAR_BACKUP_OPTIONS="--acls --xattrs --exclude-caches --no-wildcards-match-slash --sparse"

I hope that someone can find this useful. If you have any suggestions for improvement or otherwise, feel free to comment.

toolic
14.4k5 gold badges29 silver badges201 bronze badges
asked Sep 30, 2019 at 9:44
\$\endgroup\$
1
  • \$\begingroup\$ Ken Thompson's toes are curling... "Unix philosophy: Do one thing and do it well." These hundreds of lines of dense script try to fulfil too many (related) tasks, and it winds up tripping-over its own feet... KISS... \$\endgroup\$ Commented Apr 24 at 22:58

1 Answer 1

1
\$\begingroup\$

Documentation

Your configuration file has ample documentation in the form of comments. You should add header comments to the script to summarize its purpose.

UX

I like that the code prompts for my password and notifies me that it must be run as root.

It is good that the code has usage details, but it would be nice to be able to see the details without having to enter a password. For example, a -h option would be useful.

NSFW

Even if the code is not used for work, it would be better to avoid f-bombs in the usage details:

mess up your system by mistake! You can do so even when you 

Layout

The code would be easier to read and understand with 4-space indentation levels instead of 2-space. The comments should also be indented with the code:

store_partition_layout () {
 if [ "${BACKUP_TYPE,,}" == "full" ] && [ ! -z "${PART_LOCATION}" ]; then
 # Check if the directory/file already exists: 
 if [[ -e ${PART_LOCATION} ]] ; then
 echo "Error! ${PART_LOCATION} already exists. Please rename or remove it."
 exit 1
 fi 

Long lines are hard to understand as well.

answered Apr 24 at 17:14
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.