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.
-
\$\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\$Fe2O3– Fe2O32025年04月24日 22:58:23 +00:00Commented Apr 24 at 22:58
1 Answer 1
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.