#!/usr/bin/env bash # # zfs-backup.sh # # Simple backup script utilizing rsync and ZFS snapshots. # # rsync must be installed both on the server and the client. # ssh must be installed on the client. # bash must be installed on the server. # The server must use zfs and provide a dataset for each client. # # David Prandzioch # # Pass the following environment variables to the script: # # * BACKUP_DATASET : ZFS dataset to use # * BACKUP_SSH_PATH : Original data SSH path (user@host:path) # * BACKUP_SSH_PORT : SSH source port (22) # DAY_OF_WEEKLY_BACKUP=1 # monday DAY_OF_MONTHLY_BACKUP="01" # first day in month ######### DO NOT CHANGE ANYTHING DOWN HERE ######### if [ -z $BACKUP_DATASET ] then echo "Environment variable BACKUP_DATASET not set, exiting" exit 1 fi if [ -z $BACKUP_SSH_PATH ] then echo "Environment variable BACKUP_SSH_PATH not set, exiting" exit 1 fi if [ -z $BACKUP_SSH_PORT ] then echo "Environment variable BACKUP_SSH_PORT not set, exiting" exit 1 fi function delete_snapshots() { DATASET=$1 TYPE=$2 SNAPSHOTS=$(zfs list -t snapshot -o name | grep "${DATASET}@${TYPE}-") for SNAPSHOT in $SNAPSHOTS do zfs destroy $SNAPSHOT done } function sync_data() { DATASET=$1 BACKUP_SSH_PATH=$2 BACKUP_SSH_PORT=$3 MOUNTPOINT=$(zfs list -o mountpoint $DATASET | grep -v MOUNTPOINT) cd $MOUNTPOINT rsync -av --progress --delete --inplace -e "ssh -p ${BACKUP_SSH_PORT}" ${BACKUP_SSH_PATH}* . } function create_snapshot() { DATASET=$1 TYPE=$2 zfs snapshot ${DATASET}@${TYPE}-$(date +%Y-%m-%d) } sync_data $BACKUP_DATASET $BACKUP_SSH_PATH $BACKUP_SSH_PORT if [ "$(date +%d)" == "$DAY_OF_MONTHLY_BACKUP" ] then create_snapshot $BACKUP_DATASET "monthly" delete_snapshots $BACKUP_DATASET "weekly" delete_snapshots $BACKUP_DATASET "daily" elif [ "$(date +%u)" == "$DAY_OF_WEEKLY_BACKUP" ] then create_snapshot $BACKUP_DATASET "weekly" delete_snapshots $BACKUP_DATASET "daily" else create_snapshot $BACKUP_DATASET "daily" fi echo "Available snapshots for "$BACKUP_DATASET": " zfs list -t snapshot -o name | grep "${BACKUP_DATASET}@"