Last active
June 3, 2023 18:24
-
-
Save DavesCodeMusings/8b1e4f5fba963a8b6c105e32397a409d to your computer and use it in GitHub Desktop.
Not too bad backup to external disk
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| This shell script will back up files from remote systems as well as local | |
| using rsync. Default behavior is to prune any backups older than 90 days, | |
| except for Sundays. This results in daily copies for up to 90 days and weekly | |
| copies for anything older. | |
| Sample crontab entries to back up multiple hosts on a schedule: | |
| 0 6 * * * /media/backup/backup.sh lorum.home | |
| 0 7 * * * /media/backup/backup.sh ipsum.home | |
| 0 8 * * * /media/backup/backup.sh dolor.home | |
| The script takes a single command-line argument of the host's name. (Backing | |
| up the host where the script is running requires the hostname as well for | |
| directory naming purposes.) | |
| To backup remote hosts, you'll need to configure ssh keys first, so rsync | |
| can log in without a password. | |
| Date calculations are done so they are compatible with the date command | |
| supplied by busybox (used in Alpine Linux) rather than relying on added | |
| functionality in GNU date. | |
| I am sharing this script for educational purposes only. Please, for the love | |
| of Pete, don't use it to back up anything important. This script comes with | |
| NO WARRANTY, not even the implied warranty of fitness for particular purpose. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/sh | |
| BASE_DIR=/media/backup | |
| [email protected] # Comment out to disable email summary. | |
| PRUNE_DAYS=90 # Set to 0 to disable pruning, otherwise days of retention. | |
| if [ "$1" == "" ]; then | |
| echo "Usage:" | |
| echo " $0 server-name" | |
| exit 1 | |
| fi | |
| # Save space with hardlinks to files that are unchanged from yesterday. | |
| YESTERDAY=$(/bin/date -d @$(($(/bin/date +%s) - 86400)) +%Y/%m/%d) | |
| YESTERDAY_DIR=${BASE_DIR}/${1}/${YESTERDAY} | |
| HARDLINK_OPTION="--link-dest=${YESTERDAY_DIR}" | |
| [ -d ${YESTERDAY_DIR} ] || unset HARDLINK_OPTION | |
| # Destination for today's backup. | |
| TODAY_DIR=${BASE_DIR}/${1}/$(date '+%Y/%m/%d') | |
| mkdir -p ${TODAY_DIR} || exit 2 | |
| cd ${TODAY_DIR} || exit 2 | |
| # Local and remote backups have slight differences. | |
| LOG_FILE=${BASE_DIR}/${1}.log | |
| if [ "${1}" == "$(uname -n)" ]; then | |
| rsync -av ${HARDLINK_OPTION} \ | |
| --exclude-from=${BASE_DIR}/exclude.txt \ | |
| --stats \ | |
| / . >${LOG_FILE} 2>&1 | |
| else | |
| ping -c1 ${1} >${BASE_DIR}/${1}.log 2>&1 || exit 4 | |
| rsync -avz ${HARDLINK_OPTION} \ | |
| --exclude-from=${BASE_DIR}/exclude.txt \ | |
| --stats \ | |
| root@${1}:/ . >>${LOG_FILE} 2>&1 | |
| fi | |
| # Optionally remove older backup directories to save space, but keep Sundays. | |
| if [ ${PRUNE_DAYS} -ne 0 ]; then | |
| NOW=$(/bin/date +%s) # current datetime in seconds. | |
| PRUNE_AGE=$((${PRUNE_DAYS} * 86400)) # Expressed in seconds. | |
| PRUNE_DAY=$(/bin/date -d @$((${NOW} - ${PRUNE_AGE})) +%u) | |
| PRUNE_DATE=$(/bin/date -d @$((${NOW} - ${PRUNE_AGE})) +%Y/%m/%d) | |
| PRUNE_DIR=${BASE_DIR}/${1}/${PRUNE_DATE} | |
| echo "" >>${LOG_FILE} | |
| if [ ${PRUNE_DAY} -eq 7 ]; then # Sunday=7, Monday=1, Tuesday=2, etc. | |
| echo "Retaining weekly backup: ${PRUNE_DIR}" >>${LOG_FILE} | |
| else | |
| echo "Pruning ${PRUNE_DAYS} day old backup: ${PRUNE_DIR}" >>${LOG_FILE} | |
| [ -d ${PRUNE_DIR} ] && rm -Rf ${PRUNE_DIR} | |
| fi | |
| fi | |
| # Report space left on backup device in a friendly way. | |
| df -h ${BASE_DIR} | awk 'NR>1 { printf "\n%s: %s of %s (%s) used.\n", $1, $3, $2, $5 }' >>${LOG_FILE} | |
| # Email a summary. | |
| if [ "${MAIL_TO}" != "" ]; then | |
| tail -16 ${BASE_DIR}/${1}.log | mail -s "${1} backup" ${MAIL_TO} | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment