As part of the buildout of my new offsite backup server, the main goal is to back up the contents of my network to an offsite location. This shell script, sync-offsite.sh
and its related files are the main components.
|
#!/bin/sh
|
|
# File: sync-offsite.sh
|
|
# Locations:
|
|
# dns2:/etc/installed/
|
|
# /mnt/public/Support/Systems/dns2/
|
|
# Author: bgstack15
|
|
# Startdate: 2021-11-19
|
|
# Title: Script that Syncs Data to Offsite Server
|
|
# Purpose:
|
|
# History:
|
|
# Usage:
|
|
# Reference:
|
|
# Improve:
|
|
# the whole redirection spaghetti is very dangerous and probably should be rewritten/removed.
|
|
# Dependencies:
|
|
# plecho from bgscripts-core
|
|
# freeipa user, hbac rules, and sudo rules
|
|
# /etc/installed/sync-offsite.excludes
|
|
# Documentation:
|
|
# server2:/etc/installed/server2a.md
|
|
|
|
#set -e -u
|
|
|
|
RUNUID="$( < /dev/urandom tr -dc 'A-Z0-9' | head -c6 )"
|
|
LOGFILE=/var/log/sync-offsite/sync.$( date "+%F" ).log
|
|
|
|
# FUNCTIONS
|
|
mainbup() {
|
|
___target="${1}" # either "server2" or its vpn IP, hardcoded in the script below.
|
|
sudo rsync -avz -e "ssh -i /home/syncuser/.ssh/id_rsa" --rsync-path='sudo /usr/bin/rsync' --exclude-from="${EXCLUDE_FILE:-/etc/installed/sync-offsite.excludes}" \
|
|
/mnt/serverx/shares syncuser@"${___target}":/var/server2/
|
|
}
|
|
|
|
validate_mounts() {
|
|
thismount="$( mount | awk '/jon/{print $1,$3}' )"
|
|
if test "${thismount}" != "serverx:/volume1/sword /mnt/serverx" ;
|
|
then
|
|
echo "FATAL: Mount point for serverx not found. Aborted." 1>&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
validate_user() {
|
|
if test "${USER}" != "syncuser" ;
|
|
then
|
|
echo "Switching user to syncuser"
|
|
sudo su syncuser "$( readlink -f "${0}" )"
|
|
exit 0
|
|
else
|
|
:
|
|
fi
|
|
}
|
|
|
|
get_target_address() {
|
|
for word in server2.ipa.internal.com server2.remote.internal.com 10.222.0.4 ;
|
|
do
|
|
echo "testing ${word}" 1>&2
|
|
timeout 3 bash -c "echo > /dev/tcp/${word}/22"
|
|
test $? -eq 0 && { echo "${word}" ; break ; }
|
|
done
|
|
echo "using remote identifier ${word}" 1>&2
|
|
}
|
|
|
|
validate_user # make sure this is running as syncuser
|
|
|
|
# MAIN LOOP
|
|
{
|
|
echo "START sync-offsite" | plecho
|
|
{
|
|
{
|
|
validate_mounts # make sure /mnt/serverx exists
|
|
target="$( get_target_address )"
|
|
mainbup "${target}"
|
|
} 2>&1 1>&3 | unbuffer -p sed -r -e "s/^/STDERR: /" 1>&2
|
|
} 3>&1
|
|
echo "STOP sync-offsite" | plecho
|
|
} 2>&1 | unbuffer -p sed -r -e "s/^/${RUNUID} /;" | tee -a "${LOGFILE}"
|
|
|
|
yes | scp -p "${LOGFILE}" server1:/var/server1/shares/public/Support/Systems/dns2/"$( dirname "${LOGFILE}" )"
|
My shell script has some hardcoded paths, because I didn't find it worth it to move those to a config file. You will notice the --rsync-path
trick to use sudo rsync.
I also use a rather simple hostname connectivity check. I just hardcode the DNS names I set up for the remote system. Obviously that's subject to change over time if I change backup systems.
I noticed in my logs that if I prepend every single line with the user and timestamp, it's a waste. So I added a unique run id, without using some crazy long guid. I only need to differentiate between different runs on the same day, because I use a new log file per day. So it's only really necessary for when I was building out this script.
Comments