diff --git a/zsc-sync.sh b/zsc-sync.sh index 517dd64..127badd 100755 --- a/zsc-sync.sh +++ b/zsc-sync.sh @@ -56,12 +56,8 @@ resume_transfer() { handle_dataset() { DATASET=$1 RECURSIVE=$2 - D=$3 - W=$4 - M=$5 - Y=$6 - PREFIX=$7 + PREFIX=$3 if test -z "$PREFIX"; then PREFIX="zsc-" fi @@ -70,10 +66,13 @@ handle_dataset() { PREFIX="" fi - TARGET_REMOTE_DATASET="$REMOTE_ROOT_DATASET/"$(echo -e "$DATASET" | sed -r "s/\//_/g") + TARGET_REMOTE_DATASET=$4 + if test -z "$TARGET_REMOTE_DATASET"; then + TARGET_REMOTE_DATASET="$REMOTE_ROOT_DATASET/"$(echo -e "$DATASET" | sed -r "s/\//_/g") + fi echo "[$DATASET -> $TARGET_REMOTE_DATASET]" - echo -e + echo resume_transfer "$TARGET_REMOTE_DATASET" || return 0 @@ -85,7 +84,7 @@ handle_dataset() { echo "Remote snapshots: ${#REMOTE_SNAPSHOTS[@]}" echo "Local snapshots: ${#LOCAL_SNAPSHOTS[@]}" - echo -e + echo for local_snapshot in "${LOCAL_SNAPSHOTS[@]}"; do found=false @@ -107,7 +106,7 @@ handle_dataset() { done echo "Snapshots are synchronized up to $FROM_SNAPSHOT" - echo -e + echo if test ! -z "$TO_SNAPSHOT"; then echo "Synchronizing snapshots from $FROM_SNAPSHOT to $TO_SNAPSHOT ..." @@ -120,13 +119,16 @@ handle_dataset() { fi zfs send -v -p $recu $incr "$DATASET@$TO_SNAPSHOT" | ssh $REMOTE zfs receive -F -s "$TARGET_REMOTE_DATASET" || return 1 + echo echo "Done" + echo fi } init_subdataset() { DATASET=$1 PARENT_DATASET=$2 + LATEST_SYNCHRONIZED_SNAPSHOT=$3 TARGET_REMOTE_DATASET="$REMOTE_ROOT_DATASET/"$(echo -e $PARENT_DATASET | sed -r "s/\//_/g")"/"${DATASET:$(echo -e "$PARENT_DATASET" | wc -c)} @@ -146,27 +148,71 @@ init_subdataset() { echo "[$DATASET@$LOCAL_SNAPSHOT -> $TARGET_REMOTE_DATASET]" zfs send -v -p "$DATASET@$LOCAL_SNAPSHOT" | ssh $REMOTE zfs receive -F -s "$TARGET_REMOTE_DATASET" || return 1 - echo -e "Done" + echo + echo "--- Done" + echo + elif [ $(echo -e "$remote_snapshots" | grep -e "^$TARGET_REMOTE_DATASET@$LATEST_SYNCHRONIZED_SNAPSHOT\$" | wc -l) -eq 0 ]; then + echo + echo "--- Subdataset $TARGET_REMOTE_DATASET is out of date compared to parent dataset. Syncing first..." + + handle_dataset "$DATASET" false "" "$TARGET_REMOTE_DATASET" || exit 1 + + echo + echo "--- Done" + echo fi } for line in $(cat "$ZSC_CONFIG") ; do IFS=: read dataset recursive d w m y prefix <<< "$line" - echo "| ##### Dataset: $dataset Recursive: $recursive Prefix: $prefix d: $d w: $w m: $m y: $y #####" + echo + echo + echo "##### Dataset: $dataset Recursive: $recursive Prefix: $prefix d: $d w: $w m: $m y: $y #####" + echo if [ $recursive = "true" ]; then SUBDATASETS=($(zfs list -o name | grep "$dataset/")) - echo -e "| Subdatasets: ${SUBDATASETS[@]}" - echo -e '|' - for p in "${SUBDATASETS[@]}"; do - init_subdataset $p $dataset | awk '{print "| " $0}' || exit 1 + + + # Find latest synchronized parente snapshot + REMOTE_DATASET="$REMOTE_ROOT_DATASET/"$(echo -e "$dataset" | sed -r "s/\//_/g") + REMOTE_SNAPSHOTS=($(echo -e "$remote_snapshots" | grep "$REMOTE_DATASET@" | cut -d"@" -f 2)) + LOCAL_SNAPSHOTS=($(zfs list -H -t snapshot -o name -s creation "$dataset" | cut -d"@" -f 2)) + + for local_snapshot in "${LOCAL_SNAPSHOTS[@]}"; do + found=false + for remote_snapshot in "${REMOTE_SNAPSHOTS[@]}"; do + if [ "$remote_snapshot" = "$local_snapshot" ] ; then + found=true + break + fi + done + + if [ $found = true ] ; then + latest_synchronized_snapshot=$local_snapshot + fi done + echo "Latest synchronized snapshot locally: $latest_synchronized_snapshot" + echo + + + # Init subdatasets + echo "Subdatasets: ${SUBDATASETS[@]}" + echo + for p in "${SUBDATASETS[@]}"; do + init_subdataset $p $dataset "$latest_synchronized_snapshot" || exit 1 + done + echo + echo "----------" + echo fi - handle_dataset $dataset $recursive $d $w $m $y $prefix | awk '{print "| " $0}' || exit 1 + handle_dataset $dataset $recursive $prefix || exit 1 - echo -e "----------------------------------------------------------------------" + echo + echo "----------------------------------------------------------------------" + echo done