#!/bin/sh DATASET=$1 if test -z "$DATASET"; then echo "Missing dataset argument" exit 1 fi TARGET=$2 if test -z "$TARGET"; then echo "Missing target" exit 1 fi TARGET_PATH=$3 if test -z "$TARGET_PATH"; then echo "Missing target path" exit 1 fi DATE=$4 if test -z "$DATE"; then DATE=$(date +%Y-%m-%d_%H-%M) fi REMOTE_NAME="$TARGET_PATH/"$(echo -e $DATASET | sed -r "s/\//_/g") ### Resume existing transfer ### RESUME_TOKEN=$(ssh $TARGET zfs get -H -p receive_resume_token -o value "$REMOTE_NAME") if [ "$RESUME_TOKEN" != "" ] && [ "$RESUME_TOKEN" != "-" ]; then echo "Resuming interrupted transfer..." zfs send -v -t "$RESUME_TOKEN" | ssh $TARGET zfs receive -F -s "$REMOTE_NAME" || exit 1 echo "Resumed transfer finished." exit 0 fi ### Sync existing snapshots ### REMOTE_SNAPSHOTS=($(ssh $TARGET zfs list -H -t snapshot -o name -s creation $REMOTE_NAME | cut -d"@" -f 2)) LOCAL_SNAPSHOTS=($(zfs list -H -t snapshot -o name -s creation $DATASET | cut -d"@" -f 2)) echo "Remote snapshots: $REMOTE_SNAPSHOTS" for local_snapshot in "${LOCAL_SNAPSHOTS[@]}"; do echo "Syncing local snapshot $local_snapshot ..." found=false for remote_snapshot in "${REMOTE_SNAPSHOTS[@]}"; do if [ "$remote_snapshot" = "$local_snapshot" ] ; then found=true break fi done if [ $found = true ] ; then echo "> Found remotely, setting as last snapshot" LAST_SNAPSHOT=$local_snapshot EXISTING_SNAPSHOT="" else echo "> Needs sync" EXISTING_SNAPSHOT=$local_snapshot fi done ### New snapshot ### if [ "$EXISTING_SNAPSHOT" = "" ]; then NAME=$DATE else NAME=$EXISTING_SNAPSHOT fi SNAPSHOT="$DATASET@$NAME" echo "New snapshot name is: $NAME" echo "New snapshot is: $SNAPSHOT" ### Last snapshot ### echo "Last snapshot is: $LAST_SNAPSHOT" ## Perform transfer echo "Starting backup with args $DATASET $NAME $LAST_SNAPSHOT" $HOME/scripts/zfs_backup.sh $DATASET $NAME "$LAST_SNAPSHOT" $TARGET $TARGET_PATH || exit 1 ## Destroy last snapshot echo "Destroying last snapshot..." zfs destroy "$DATASET@$LAST_SNAPSHOT" || exit 1 echo "Backup finished."