#!/bin/bash
-# List of files/directories to backup
-BKP_FILES_LIST="/etc /root /srv /usr/local/bin"
-
-# Where to put backup
+# Directory where to put the resulting backup file:
BKP_DEST_DIR="/mnt/nas/backup"
+
+# Save Debian configuration:
+DPKG_CONFIG="/tmp/$(hostname)-dpkg-config"
+
+# List of files/directories to backup:
+BKP_FILES_LIST="\
+ /etc \
+ /root \
+ /opt \
+ /usr/local/bin \
+ ${DPKG_CONFIG} \
+"
+
+# Additional translations: example /mnt/projets --> archive_label/projets
+DIR_OPTS="--transform "s@/mnt/projets/@${archive_label}/projets/@" ${DIR_OPTS}"
+
+# DPKG_CONFIG: Translate /tmp --> archive_label
+DIR_OPTS="--transform "s@/tmp/@${archive_label}/@" ${DIR_OPTS}"
+
+# Files to exclude from backup:
+cat >> ${EXC_LIST} << "EOF"
+ /opt/brave*
+ /opt/containerd
+EOF
+
+hvbackup_pre_script()
+{
+ dpkg --list > ${DPKG_CONFIG}
+
+ # Special case for linux and u-boot repos:
+ for d in linux u-boot; do
+ log_dbg "Clean repos: ${d}"
+ cd ${d}
+ make mrproper 1> /dev/null 2>&1
+ done
+}
+
+hvbackup_post_script()
+{
+ rm -f ${DPKG_CONFIG}
+}
#
# Creates a single compressed archive.
-if [ ! -f /etc/backup.conf ]; then
- echo "Error: missing /etc/backup.conf configuration file."
- exit 1
-fi
+set -e
-# Read list of backup files/directories
-source /etc/backup.conf
+PROG_NAME="`readlink -e $0`"
+PROG_PATH=$(dirname ${PROG_NAME})
+source ${PROG_PATH}/hvutilities.sh
-# Set default value if not specified
-: ${BKP_DEST_DIR:="./"}
+# Default values
+local_user="$(whoami)"
+archive_label="backup-$(hostname)-${local_user}-$(date '+%Y-%m-%d')"
+encrypt="0"
+config_file="${HOME}/.hv-backup.conf"
-# Default value
-ARCHIVE_LABEL="backup-data-amd64-`date '+%Y-%m-%d'`"
+hvbackup_pre_script()
+{
+ log_dbg "Default hvbackup_pre_script(), can be overrided in configuration file"
+}
-# Exclude files list
-EXC_LIST="/tmp/hv-backup-exclude-list"
+hvbackup_post_script()
+{
+ log_dbg "Default hvbackup_post_script(), can be overrided in configuration file"
+}
print_usage()
{
- echo "$(basename $0) - Backup files/directories."
- echo "Usage: $(basename $0) [-h] [--label "label"]"
+ log_info "${PROG_NAME} -- Backup files/directories"
+ log_info "Usage: ${PROG_NAME} [OPTIONS...]"
+ log_info
+ log_info "Options:"
+ log_info " -c config-file (default HOME/.hv-backup.conf)"
+ log_info " -d debug mode"
+ log_info " -g encrypt with GPG"
+ log_info " -l archive_label (default backup-HOSTNAME-USER-DATE)"
+ log_info " -h display this help and exit"
+ log_info
}
-if [ ${#} -gt 0 ]; then
- if [ "x${1}" = "x-h" ]; then
- print_usage
- exit 0
- fi
- if [ "x${1}" = "x--label" ]; then
- if [ $# -lt 2 ]; then
- echo "Missing arguments for --label option"
+while getopts "c:dgl:" flag ;do
+ case ${flag} in
+ c)
+ config_file="${OPTARG}"
+ ;;
+ d)
+ debug="1"
+ ;;
+ g)
+ encrypt=1
+ ;;
+ l)
+ archive_label="${OPTARG}"
+ ;;
+ h)
print_usage
- exit 1
- fi
+ exit 0
+ ;;
+ ?)
+ log_err "${PROG_NAME}: Option invalide: ${OPTARG}."
+ log_info "Essayez \`${PROG_NAME} -h' pour plus d'informations."
+ exit 1
+ ;;
+ esac
+done
+shift `expr "${OPTIND}" - 1`
+
+# `$#' now represents the number of arguments after the options.
+# `$1' is the first argument, etc.
+if [ $# -ne 0 ]; then
+ log_err "${PROG_NAME}: Too many arguments."
+ log_info "Essayez \`${PROG_NAME} -h' pour plus d'informations."
+ exit 1
+fi
- ARCHIVE_LABEL=${2}
- shift
- shift
+log_dbg "archive_label: $archive_label"
- if [ $# = 0 ]; then
- echo "No directory to backup specified"
- print_usage
- exit 1
- fi
- else
- echo "Unknown arguments: ${@}"
- print_usage
- exit 1
- fi
-fi
+# Translate / --> archive_label, so that the decompression will be
+# made into a folder named archive_label:
+DIR_OPTS="--transform "s@/@${archive_label}/@""
-ARCHIVE_NAME=${BKP_DEST_DIR}/${ARCHIVE_LABEL}.tar.bz2
+if [ ! -f ${config_file} ]; then
+ log_err "Error: missing configuration file: ${config_file}"
+ exit 1
+fi
-echo "ARCHIVE_LABEL=$ARCHIVE_LABEL"
+# Exclude files list
+EXC_LIST="$(mktemp --tmpdir=/tmp hv-backup-exclude-listXXXXXX)"
cat > ${EXC_LIST} << "EOF"
+/etc/shadow
/media/*
/proc/*
/dev/*
*/.gvfs*
EOF
+# Read list of backup files/directories
+source ${config_file}
+
+if [ "${BKP_FILES_LIST}" = "" ]; then
+ log_err "Error: missing BKP_FILES_LIST variable in ${config_file}"
+ exit 1
+fi
+
+# Set default value if not specified
+if [ "${BKP_DEST_DIR}" = "" ]; then
+ BKP_DEST_DIR="./"
+else
+ mkdir -p ${BKP_DEST_DIR}
+fi
+
+log_dbg "DIR_OPTS: ${DIR_OPTS}"
+
+ARCHIVE_NAME=${BKP_DEST_DIR}/${archive_label}.tar.bz2
+
+if [ -f ${ARCHIVE_NAME} ]; then
+ log_err "Cannot overwrite existing destination file: ${ARCHIVE_NAME}"
+ exit 1
+fi
+
+hvbackup_pre_script
+
# Finding sockets, and listing them in the exclude file.
# Errors and warnings must be discarded because of .gvfs directory for example.
-# Even when using -prune option, find exits with a non-zero status when resding
+# Even when using -prune option, find exits with a non-zero status when reading
# .gvfs
+set +e
find ${BKP_FILES_LIST} -type s >> ${EXC_LIST} 2> /dev/null
+set -e
# Archiving
-tar jcf ${ARCHIVE_NAME} ${BKP_FILES_LIST} \
- --label="${ARCHIVE_LABEL}" \
- --ignore-failed-read \
+tar \
+ ${DIR_OPTS} \
--exclude-backups \
--exclude-caches \
--exclude-from=${EXC_LIST} \
- --absolute-names \
- --totals
+ -j -c -f ${ARCHIVE_NAME} ${BKP_FILES_LIST} \
+ --label="${archive_label}" \
+ --ignore-failed-read \
+ --absolute-names
+
+if [ "${encrypt}" = "1" ]; then
+ export GPG_TTY=$(tty)
+ gpg -c ${ARCHIVE_NAME}
+
+ if [ ${?} -eq 0 ]; then
+ rm -f ${ARCHIVE_NAME}
+ fi
+fi
+
+hvbackup_post_script
+# Cleanup
rm ${EXC_LIST}
exit $?