645 lines
20 KiB
Bash
Executable File
645 lines
20 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
##
|
|
# Copyright (C) 2013-2016 Janek Bevendorff
|
|
# Website: http://www.refining-linux.org/
|
|
#
|
|
# Script to push backups to a remote rsync backup server.
|
|
# Read the source code or use with --help parameter for
|
|
# further usage information.
|
|
#
|
|
# The MIT License (MIT)
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
# of this software and associated documentation files (the "Software"), to deal
|
|
# in the Software without restriction, including without limitation the rights
|
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
# copies of the Software, and to permit persons to whom the Software is
|
|
# furnished to do so, subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be included in
|
|
# all copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
# THE SOFTWARE.
|
|
##
|
|
|
|
|
|
###############################################################################
|
|
# Source configs
|
|
###############################################################################
|
|
|
|
. /etc/rs-backup/client-config
|
|
|
|
|
|
###############################################################################
|
|
# Additional internal config
|
|
###############################################################################
|
|
|
|
_VERSION=$(rs-version version)
|
|
_GLOBAL_INCLUSION_PATTERN_FILE="/etc/rs-backup/include-files"
|
|
_FORCED_INCLUSION_PATTERN_FILE=""
|
|
_SKIP_HOME_DIRS=false
|
|
_FORCED_LOG_FILE=""
|
|
_QUIET_MODE=false
|
|
_VERBOSE_MODE=false
|
|
_SHOW_PROGRESS=false
|
|
_DRY_RUN=false
|
|
_FORCE_RUN=false
|
|
_ERROR_COUNT=0
|
|
|
|
if [ $(id -u) -eq 0 ]; then
|
|
_RUNFILE="/var/run/rs-backup/rs-backup-run.pid"
|
|
else
|
|
_RUNFILE="${HOME}/.rs-backup/rs-backup-run.pid"
|
|
fi
|
|
|
|
|
|
###############################################################################
|
|
# Function declarations
|
|
###############################################################################
|
|
|
|
# Print usage instructions to the screen
|
|
#
|
|
# Usage: print_help
|
|
print_help() {
|
|
rs-version headline rs-backup-run
|
|
rs-version copyright
|
|
cat << HELP
|
|
|
|
Push backup to rsync backup server over SSH.
|
|
|
|
If run as root and with no parameters, a full backup of all files and folders
|
|
specified in '${_GLOBAL_INCLUSION_PATTERN_FILE}' and all home directories
|
|
containing a proper backup config file will be pushed.
|
|
|
|
If invoked without root privileges, only the home directory of the current
|
|
user will be backed up.
|
|
|
|
Usage: $(basename $0) [OPTION]...
|
|
|
|
Options:
|
|
-r, --remote-host=HOST The remote host to connect to
|
|
--remote-user=NAME The username to use for logging into the remote server
|
|
(%h will be replaced with the host name of this
|
|
machine and %u with your username)
|
|
--push-module=NAME The remote rsync server module
|
|
--ssh-options=OPTS Additional SSH options (will be merged with the default
|
|
options set in the rs-backup client-config file)
|
|
-o, --rsync-options=OPTS Additional options for rsync
|
|
-n, --dry-run Perform a test run (same as the --dry-run option for
|
|
rsync). Enable --verbose mode for useful control output
|
|
-s, --no-home-dirs Don't back up home dirs, only perform global system
|
|
backup (root only)
|
|
-i, --include-from=FILE Specify an alternate inclusion pattern file
|
|
This will override the default setting. If the script
|
|
is run as root, only the system backup will be
|
|
performed, no additional home directories will be
|
|
backed up
|
|
-l, --log-level=NUM Set log level to NUM (between 0 and 4)
|
|
--log-file=FILE Set a different log file location
|
|
-f, --force-run Force rs-backup to run, even if a lock file exists
|
|
-q, --quiet Don't print any error messages or warnings to the
|
|
screen (only write to log file)
|
|
-v, --verbose Print all messages of the current debug level
|
|
-p, --progress Print file transfer information to the terminal
|
|
-h, --help Print this help and exit
|
|
HELP
|
|
}
|
|
|
|
# Write log messages to screen and/or log file
|
|
#
|
|
# Usage: write_log <log level> <log message>
|
|
#
|
|
write_log() {
|
|
local log_msg
|
|
local log_date
|
|
local log_dest
|
|
|
|
if [ $1 -gt 0 ] && [ $1 -le $LOG_LEVEL ]; then
|
|
case $1 in
|
|
1) log_msg="ERROR: ${2}" ;;
|
|
2) log_msg="WARNING: ${2}" ;;
|
|
3) log_msg="INFO: ${2}" ;;
|
|
*) log_msg="DEBUG: ${2}" ;;
|
|
esac
|
|
|
|
log_date="[$(date)]"
|
|
full_log_msg="${log_date} ${log_msg}"
|
|
|
|
if [ "${_FORCED_LOG_FILE}" != "" ]; then
|
|
log_dest=${_FORCED_LOG_FILE}
|
|
elif [ $(id -u) -eq 0 ]; then
|
|
log_dest=${LOG_FILE}
|
|
elif [ "${HOME}" != "" ] && [ "${USER_LOG_FILE}" != "" ]; then
|
|
log_dest=${HOME}/${USER_LOG_FILE}
|
|
else
|
|
echo "WARNING: Couldn't determine valid log file location, using '/var/tmp'..." >&2
|
|
log_dest="/var/tmp/${LOG_FILE}"
|
|
fi
|
|
|
|
if ! test_file_perms "w" "${log_dest}"; then
|
|
echo "ERROR: Couldn't open log file for writing, redirecting to STDOUT!" >&2
|
|
echo "${log_date} ${log_msg}" >&1
|
|
else
|
|
echo "${log_date} ${log_msg}" >> "${log_dest}"
|
|
fi
|
|
|
|
if ! $_QUIET_MODE && [ $1 -eq 1 ]; then
|
|
$_VERBOSE_MODE || $PRINT_ERRORS && echo "${log_msg}" >&2
|
|
elif ! $_QUIET_MODE && [ $1 -le 2 ]; then
|
|
$_VERBOSE_MODE || $PRINT_WARNINGS && echo "${log_msg}" >&2
|
|
elif ! $_QUIET_MODE && [ $1 -gt 2 ]; then
|
|
$_VERBOSE_MODE && echo "${log_msg}" >&1
|
|
fi
|
|
|
|
fi
|
|
|
|
# Increase error count
|
|
if [ $1 -eq 1 ]; then
|
|
_ERROR_COUNT=$(($_ERROR_COUNT + 1))
|
|
fi
|
|
}
|
|
|
|
|
|
# Create runfile containing current PID
|
|
#
|
|
# Usage: create_runfile
|
|
#
|
|
create_runfile() {
|
|
write_log 4 "Creating runfile (PID=${$}) at '${_RUNFILE}'..."
|
|
if [ ! -d "$(dirname $_RUNFILE)" ]; then
|
|
mkdir -p "$(dirname $_RUNFILE)"
|
|
fi
|
|
echo $$ > "$_RUNFILE"
|
|
}
|
|
|
|
# Remove created runfile
|
|
#
|
|
# Usage: remove_runfile
|
|
#
|
|
remove_runfile() {
|
|
write_log 4 "Removing runfile at '${_RUNFILE}'..."
|
|
rm -f "$_RUNFILE"
|
|
# also remove parent directory, but only if empty
|
|
# redirect error output since --ignore-fail-on-non-empty is not POSIX
|
|
rmdir "$(dirname $_RUNFILE)" > /dev/null 2>&1
|
|
}
|
|
|
|
# Handle script termination by external signals.
|
|
#
|
|
# Usage: handle_signals
|
|
#
|
|
handle_exit_signal() {
|
|
write_log 1 "Program terminated upon user request."
|
|
remove_runfile
|
|
exit 1
|
|
}
|
|
|
|
# Show a desktop notification using notify-send
|
|
#
|
|
# Usage: desktop_notify <type: INFO|WARNING|ERROR> <title> <message>
|
|
#
|
|
desktop_notify() {
|
|
local icon
|
|
local urgency
|
|
local user
|
|
|
|
if [[ "$(uname -o)" == "Cygwin" ]]; then
|
|
# not implemented
|
|
return
|
|
fi
|
|
|
|
command -v notify-send > /dev/null 2>&1
|
|
if [ $? -ne 0 ]; then
|
|
# notify-send not available
|
|
return
|
|
fi
|
|
|
|
if $_QUIET_MODE || $_DRY_RUN; then
|
|
return
|
|
fi
|
|
|
|
user=$(who | awk '/:0/ { print $1; exit; }')
|
|
if [ $(id -u) -ne 0 ] && [[ "$user" != "" ]] && [ $(id -u "$user") -ne $(id -u) ]; then
|
|
# we're neither root nor the current user on display :0.0,
|
|
# so don't show any notification
|
|
return
|
|
fi
|
|
|
|
case $1 in
|
|
"ERROR")
|
|
icon="dialog-error.png"
|
|
urgency="critical"
|
|
;;
|
|
"WARNING")
|
|
icon="dialog-warning.png"
|
|
urgency="normal"
|
|
;;
|
|
"SUCCESS")
|
|
icon="task-complete.png"
|
|
urgency="low"
|
|
;;
|
|
*)
|
|
icon="dialog-information.png"
|
|
urgency="low"
|
|
;;
|
|
esac
|
|
|
|
if [[ "$user" != "" ]]; then
|
|
sudo -u "$user" DISPLAY=":0.0" notify-send -i "$icon" -u "$urgency" "rs-backup: $2" "$3"
|
|
fi
|
|
}
|
|
|
|
# Test if a file is readable and/or writeable
|
|
#
|
|
# Usage: test_file_perms <mode: r|w|rw> <filename>
|
|
#
|
|
test_file_perms() {
|
|
local perms=$1
|
|
local filename=$2
|
|
local result
|
|
|
|
if [ "${perms}" == "r" ]; then
|
|
[ -f "${filename}" ] && [ -r "${filename}" ]
|
|
elif [ "${perms}" == "w" ]; then
|
|
[ -f "${filename}" -a -w "${filename}" ] || [ ! -e "${2}" -a -w "$(dirname ${2})" ]
|
|
elif [ "${perms}" == "rw" ]; then
|
|
[ -f "${filename}" ] && [ -w "${filename}" ] && [ -r "${filename}" ]
|
|
fi
|
|
|
|
return $?
|
|
}
|
|
|
|
# Generate and return remote user name for SSH login
|
|
#
|
|
# Usage: get_remote_username [<local username>] [<local hostname>]
|
|
#
|
|
get_remote_username() {
|
|
local username=$1
|
|
local hostname=$2
|
|
|
|
if [ "${username}" == "" ]; then
|
|
username=$(id -un)
|
|
fi
|
|
|
|
if [ "${hostname}" == "" ]; then
|
|
hostname=$(hostname)
|
|
fi
|
|
|
|
echo $(echo ${REMOTE_USER} | sed "s/%h/${hostname}/" | sed "s/%u/${username}/")
|
|
}
|
|
|
|
# Get a stripped down version of the /etc/passwd file with all non-system users,
|
|
# their UIDs, GIDs, realpath'd home directories and shells
|
|
# Users whose home directories don't actually exist are skipped
|
|
#
|
|
# Usage: get_processed_passwd_file
|
|
#
|
|
get_processed_passwd_file() {
|
|
local line
|
|
local username
|
|
local uid
|
|
local gid
|
|
local home_dir
|
|
local shell
|
|
|
|
cat /etc/passwd | while read line; do
|
|
uid=$(echo -n "${line}" | cut -d ":" -f 3)
|
|
|
|
if [ $uid -lt 1000 ]; then
|
|
continue
|
|
fi
|
|
|
|
home_dir=$(echo -n "${line}" | cut -d ":" -f 6)
|
|
home_dir=$(realpath "${home_dir}")
|
|
|
|
if [ ! -d "${home_dir}" ]; then
|
|
continue
|
|
fi
|
|
|
|
username=$(echo -n "${line}" | cut -d ":" -f 1)
|
|
gid=$(echo -n "${line}" | cut -d ":" -f 4)
|
|
shell=$(echo -n "${line}" | cut -d ":" -f 7)
|
|
|
|
echo "${username}:x:${uid}:${gid}::${home_dir}:${shell}"
|
|
done
|
|
}
|
|
|
|
# Back up a directory.
|
|
# The third parameter is optional and specifys the user under whose
|
|
# privileges the backup will be performed
|
|
#
|
|
# Usage: perform_backup <inclusion pattern file> <destination> [<username>]
|
|
#
|
|
perform_backup() {
|
|
local inclusion_pattern_file=$1
|
|
local destination=$2
|
|
local username=$3
|
|
local msg
|
|
local backup_cmd
|
|
local ssh_cmd
|
|
local rsync_opts="${RSYNC_OPTIONS}"
|
|
local exit_code
|
|
local tee_device="/dev/tty"
|
|
|
|
if $_DRY_RUN; then
|
|
rsync_opts+=" --dry-run"
|
|
fi
|
|
|
|
if $_SHOW_PROGRESS; then
|
|
rsync_opts+=" --progress" # append to rsync_opts: preserves other options (e.g. --dry-run)
|
|
elif $_VERBOSE_MODE; then # --progress implies --verbose
|
|
rsync_opts+=" --verbose"
|
|
else
|
|
tee_device="/dev/null"
|
|
rsync_opts+=" --quiet"
|
|
fi
|
|
|
|
if [ "${username}" == "" ]; then
|
|
username=$(id -un)
|
|
fi
|
|
|
|
if [ "${_FORCED_INCLUSION_PATTERN_FILE}" != "" ]; then
|
|
inclusion_pattern_file=${_FORCED_INCLUSION_PATTERN_FILE}
|
|
fi
|
|
|
|
if ! test_file_perms "r" "${inclusion_pattern_file}"; then
|
|
write_log 1 "Pattern file '${inclusion_pattern_file}' does not exist or is not readable!"
|
|
return 1
|
|
fi
|
|
|
|
if [ "${SSH_OPTIONS}" != "" ]; then
|
|
ssh_cmd="ssh "$(echo -n "${SSH_OPTIONS}" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g') # added missing space
|
|
else
|
|
ssh_cmd="ssh"
|
|
fi
|
|
|
|
backup_cmd="rsync \
|
|
--rsh=\"${ssh_cmd}\" \
|
|
--archive \
|
|
--delete \
|
|
--delete-excluded \
|
|
--exclude=\"${_RUNFILE}\" \
|
|
--exclude=\"${LOG_FILE}\" \
|
|
--exclude=\"${USER_LOG_FILE}\" \
|
|
--include-from=\"${inclusion_pattern_file}\" \
|
|
--exclude=\"*\" \
|
|
${rsync_opts} \
|
|
/ \
|
|
\"${destination}\""
|
|
|
|
write_log 4 "This is the command about to be run: $(echo ${backup_cmd})"
|
|
|
|
set -o pipefail
|
|
|
|
if [ $(id -u) -eq 0 ] && [ "${username}" != "$(id -un)" ]; then
|
|
write_log 4 "Running backup with privileges of user '${username}' (UID: $(id -u ${username}))..."
|
|
msg=$(su - "${username}" -c "${backup_cmd}" 3>&1 1>&2 2>&3- | tee "${tee_device}")
|
|
elif [ $(id -u) -ne 0 ] && [ "${username}" != "$(id -un)" ]; then
|
|
write_log 1 "Cannot run run backup as user '${username}' (UID: $(id -u ${username}), missing root privileges!"
|
|
return 1
|
|
else
|
|
msg=$(sh -c "${backup_cmd}" 3>&1 1>&2 2>&3- | tee "${tee_device}")
|
|
fi
|
|
|
|
exit_code=$?
|
|
|
|
if [ ${exit_code} -ne 0 ]; then
|
|
write_log 1 "Backup failed! Error message: ${msg}"
|
|
desktop_notify "ERROR" "Backup failed!" "Backup for user '${username}' failed!<br>Please refer to your log files for further information."
|
|
return ${exit_code}
|
|
else
|
|
write_log 3 "Backup finished."
|
|
fi
|
|
}
|
|
|
|
# Back up selected system files
|
|
#
|
|
# Usage: back_up_system
|
|
#
|
|
back_up_system() {
|
|
if [ $(id -u) -ne 0 ]; then
|
|
write_log 1 "Cannot perform system backup unless run as root!"
|
|
return 1
|
|
fi
|
|
|
|
write_log 4 "Entering directory '/root'..."
|
|
cd /root
|
|
|
|
if $_DRY_RUN; then
|
|
write_log 3 "Starting global system backup (DRY RUN)..."
|
|
else
|
|
write_log 3 "Starting global system backup..."
|
|
fi
|
|
perform_backup "${_GLOBAL_INCLUSION_PATTERN_FILE}" "$(get_remote_username root)@${REMOTE_HOST}::${PUSH_MODULE}"
|
|
return $?
|
|
}
|
|
|
|
# Back up single home directory
|
|
#
|
|
# Usage: back_up_single_home_dir <home dir> <username>
|
|
#
|
|
back_up_single_home_dir() {
|
|
local home_dir=$(realpath "${1}")
|
|
local username=$2
|
|
|
|
# Don't back up home directory if no files are marked for backup
|
|
if [ ! -f "${home_dir}/${INCLUSION_PATTERN_FILE}" ]; then
|
|
write_log 4 "Skipping '${home_dir}', because '${INCLUSION_PATTERN_FILE}' does not exist."
|
|
return
|
|
fi
|
|
|
|
# Also don't create a backup if no SSH key exists and no custom SSH options were specified
|
|
if [ ! -f "${home_dir}/.ssh/id_rsa" ] && [ ! -f "${home_dir}/.ssh/config" ] && [ "${SSH_OPTIONS}" == "" ]; then
|
|
write_log 4 "Skipping '${home_dir}', because no proper SSH key could be found."
|
|
return
|
|
fi
|
|
|
|
write_log 4 "Entering directory '${home_dir}'..."
|
|
cd "${home_dir}"
|
|
|
|
if $_DRY_RUN; then
|
|
write_log 3 "Starting backup of '${home_dir}' (DRY RUN)..."
|
|
else
|
|
write_log 3 "Starting backup of '${home_dir}'..."
|
|
fi
|
|
perform_backup "${home_dir}/${INCLUSION_PATTERN_FILE}" "$(get_remote_username ${username})@${REMOTE_HOST}::${PUSH_MODULE}" "${username}"
|
|
return $?
|
|
}
|
|
|
|
# Back up all home dirs
|
|
#
|
|
# Usage: back_up_home_dirs
|
|
#
|
|
back_up_home_dirs() {
|
|
local exit_code=0
|
|
write_log 3 "Starting backup of all home directories..."
|
|
|
|
get_processed_passwd_file | while read line; do
|
|
back_up_single_home_dir "$(echo -n ${line} | cut -d ':' -f 6)" "$(echo -n ${line} | cut -d ':' -f 1)"
|
|
exit_code=$(($exit_code | $?))
|
|
done
|
|
|
|
return $exit_code
|
|
}
|
|
|
|
# Parse command line args
|
|
#
|
|
# Usage: parse_cmd_args <cmd arg line>
|
|
#
|
|
parse_cmd_args() {
|
|
local args
|
|
local name=$(basename $0)
|
|
|
|
if [ "$1" == "" ]; then
|
|
return
|
|
fi
|
|
|
|
getopt -T > /dev/null
|
|
if [ $? -ne 4 ]; then
|
|
write_log 1 "Need GNU getopt for command line parameter parsing!"
|
|
exit 1;
|
|
fi
|
|
|
|
args=$(getopt \
|
|
-s sh \
|
|
-o "r:o:nsi:l:fqvph" \
|
|
-l "remote-host:,remote-user:,push-module:,ssh-options:,rsync-options:,dry-run,no-home-dirs,include-from:,log-level:,log-file:,force-run,quiet,verbose,progress,help" \
|
|
-n "${name}" \
|
|
-- "${@}")
|
|
|
|
if [ $? -ne 0 ]; then
|
|
exit 1
|
|
fi
|
|
|
|
eval set -- "${args}"
|
|
|
|
while true; do
|
|
case "$1" in
|
|
"-r"|"--remote-host")
|
|
REMOTE_HOST=$2
|
|
shift 2 ;;
|
|
"--remote-user")
|
|
REMOTE_USER=$2
|
|
shift 2 ;;
|
|
"--push-module")
|
|
PUSH_MODULE=$2
|
|
shift 2 ;;
|
|
"--ssh-options")
|
|
SSH_OPTIONS="${SSH_OPTIONS} ${2}"
|
|
shift 2 ;;
|
|
"-o"|"--rsync-options")
|
|
RSYNC_OPTIONS="${RSYNC_OPTIONS} $2"
|
|
shift 2 ;;
|
|
"-n"|"--dry-run")
|
|
_DRY_RUN=true
|
|
shift ;;
|
|
"-s"|"--no-home-dirs")
|
|
_SKIP_HOME_DIRS=true
|
|
shift ;;
|
|
"-i"|"--include-from")
|
|
# File must exist and be readable
|
|
! test_file_perms "r" "${2}" && echo "$name: '${2}' does not exist or is not readable!" >&2 && exit 1
|
|
_FORCED_INCLUSION_PATTERN_FILE=$2
|
|
_SKIP_HOME_DIRS=true
|
|
shift 2 ;;
|
|
"-l"|"--log-level")
|
|
LOG_LEVEL=$2;
|
|
shift 2 ;;
|
|
"--log-file")
|
|
# Test if file is writeable
|
|
! test_file_perms "w" "${2}" && echo "$name: '${2}' is not writeable!" >&2 && exit 1
|
|
_FORCED_LOG_FILE=$2
|
|
shift 2 ;;
|
|
"-f"|"--force-run")
|
|
_FORCE_RUN=true
|
|
shift ;;
|
|
"-q"|"--quiet")
|
|
_QUIET_MODE=true
|
|
shift ;;
|
|
"-v"|"--verbose")
|
|
! $_QUIET_MODE && _VERBOSE_MODE=true
|
|
shift ;;
|
|
"-p"|"--progress")
|
|
! $_QUIET_MODE && _SHOW_PROGRESS=true
|
|
shift ;;
|
|
"-h"|"--help")
|
|
print_help
|
|
exit ;;
|
|
*)
|
|
shift
|
|
break ;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
###############################################################################
|
|
# Initialize the actual backup
|
|
###############################################################################
|
|
|
|
# Register exit trap to catch signals and cleanly shut down the script
|
|
trap handle_exit_signal SIGHUP SIGINT SIGTERM
|
|
|
|
parse_cmd_args "$@"
|
|
|
|
# Check if a backup is already running
|
|
if [ -f "$_RUNFILE" ] && ! $_FORCE_RUN; then
|
|
write_log 1 "rs-backup is already running as PID $(<$_RUNFILE)."
|
|
write_log 1 "Please finish any running backups before starting a new one."
|
|
write_log 1 "If you're sure you want to run another backup, either remove the runfile at " \
|
|
"'$_RUNFILE' or use the '--force-run' parameter."
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -f "$_RUNFILE" ]; then
|
|
write_log 4 "No other backup running, ready to start."
|
|
elif $_FORCE_RUN; then
|
|
write_log 4 "Backup already running as PID $(<$_RUNFILE), forcing parallel backup..."
|
|
fi
|
|
|
|
create_runfile
|
|
|
|
# Backup exit code (0 if all backups have finished successfully)
|
|
_exit_code=$?
|
|
|
|
# Check if script has been invoked as root
|
|
if [ $(id -u) -eq 0 ]; then
|
|
write_log 4 "Running as root, performing global system backup..."
|
|
desktop_notify "INFO" "Full system backup" "rs-backup is starting a full system backup..."
|
|
back_up_system
|
|
_exit_code=$(($_exit_code | $?))
|
|
|
|
if ! $_SKIP_HOME_DIRS; then
|
|
back_up_home_dirs
|
|
_exit_code=$(($_exit_code | $?))
|
|
else
|
|
write_log 3 "Skipping home directory backup as requested."
|
|
fi
|
|
else
|
|
write_log 3 "Running without root privileges, only backing up user home directory..."
|
|
if [ "${HOME}" != "" ]; then
|
|
desktop_notify "INFO" "Home directory backup" "rs-backup is starting a home directory backup (unprivileged)..."
|
|
back_up_single_home_dir "$(realpath ${HOME})" "$(id -nu)"
|
|
_exit_code=$(($_exit_code | $?))
|
|
else
|
|
write_log 2 "Current user has no home directory, skipping."
|
|
fi
|
|
fi
|
|
|
|
if [ $_exit_code -eq 0 ]; then
|
|
desktop_notify "SUCCESS" "Backup finished" "Your backup has successfully finished"
|
|
fi
|
|
|
|
remove_runfile
|
|
|
|
write_log 4 "Done."
|
|
|
|
if [ $_ERROR_COUNT -gt 0 ]; then
|
|
exit 1
|
|
fi
|