#!/bin/bash # A script which runs, largely on the remote machine, to prepare for backup # Jobs to do: # * Exclude files which are only found in packages # * List all packages which are installed # * (optionally) dump MySQL into a file # * (optionally) dump PostgreSQL into a file CONFDIR=/etc/chem-zfs-backup-server/zfs-rsync.d SSH="ssh -p ${SSHPORT:-22} -o ConnectTimeout=10" SCP="scp -P ${SSHPORT:-22}" set -xv SERVER=$1 if [ -z $SERVER ] ; then echo $0 Server exit 1 fi ( set -e # Has the package status changed since last time we generated the list of files? if $SSH root@$SERVER [ /var/lib/dpkg/status -nt /var/adm/backup/package-files ] ; then # Need to rebuild package-files $SSH root@$SERVER " set -e set -o pipefail umask 077 FILELIST=\`tempfile\` CONFLIST=\`tempfile\` DIFFLIST=\'tempfile\' mkdir -p /var/adm/backup # Which packages are installed? dpkg --get-selections | awk ' { print \$1 ; } ' >/var/adm/backup/packages cat /var/lib/dpkg/info/*.list | while read F ; do [ -f \"\$F\" ] && echo \"\$F\" ; done | sort > \$FILELIST awk '/Description:/ { flag = 0 } ; flag == 1 { print \$1 ; } ; /Conffiles:/ { flag = 1 } ; ' </var/lib/dpkg/status | sort >\$CONFLIST # ignore the fact that diff exits non-zero when differences are found set +e diff -u \$FILELIST \$CONFLIST > \$DIFFLIST set -e cat \$DIFFLIST | grep ^-/ | sed s/^-// | tr '\\n' '\\0' | xargs -n1 -0 realpath >/var/adm/backup/package-files rm \$FILELIST \$CONFLIST \$DIFFLIST " mkdir -p $CONFDIR/$SERVER $SCP -q root@$SERVER:/var/adm/backup/package-files $CONFDIR/$SERVER/exclude fi # Ensure that the excludes file exists, even if we haven't updated it this time if [ ! -f $CONFDIR/$SERVER/exclude ] ; then mkdir -p $CONFDIR/$SERVER $SCP -q root@$SERVER:/var/adm/backup/package-files $CONFDIR/$SERVER/exclude fi # If we can identify this as a xen VM, add some extra dirs to the exclude list # because they include some files built by the kernel package but are not # provided by it. # systemd-detect-virt is present on all our Ubuntu VMs so is hopefully a # reliable method to use # NB this returns non-zero on a non-virtual machine so we don't mind # the return value set +e VIRT_TYPE=$(ssh root@$SERVER systemd-detect-virt 2>/dev/null) set -e if [ "$VIRT_TYPE" == "xen" ] ; then cat<<EOF >> $CONFDIR/$SERVER/exclude /lib/modules /lib/firmware EOF fi if $SSH root@$SERVER id postgres >/dev/null 2>&1 ; then PGVER=$($SSH root@$SERVER pg_lsclusters| awk -F '[. ]+' '/online/ { print $1 }') if [[ -n "$PGVER" ]]; then if (( "$PGVER" >= 12 )) ; then $SSH root@$SERVER "umask 077; su -c 'pg_dumpall --clean' postgres |gzip -9 >/var/adm/backup/postgres" || echo Postgres failed on $SERVER else $SSH root@$SERVER "umask 077; su -c 'pg_dumpall --oids --clean' postgres |gzip -9 >/var/adm/backup/postgres" || echo Postgres failed on $SERVER fi fi fi $SSH root@$SERVER " set -e # Ensure that things are not readable where they ought not to be umask 077 # Save the package configuration info which debconf-get-selections >/dev/null 2>&1 || apt-get install debconf-utils which rsync >/dev/null 2>&1 || apt-get install rsync debconf-get-selections >/var/adm/backup/debconf # Dump MySQL, if the root user has access set +e systemctl is-enabled mysql --quiet 2>/dev/null MYSQL_ENABLED=\$? set -e if [ \$MYSQL_ENABLED -eq 0 ] ; then if [ -f /root/.my.cnf ] ; then DEFAULTS_FILE=/root/.my.cnf else DEFAULTS_FILE=/etc/mysql/debian.cnf fi mysqldump --defaults-file=\$DEFAULTS_FILE --all-databases >/var/adm/backup/mysql fi " echo Prepared $SERVER `date` ) >/var/log/chem-zfs-backup-server/${SERVER}-prepare 2>&1