#!/bin/bash # ZSC - zfs snapshot cron CONFIG_FILE="$HOME/.zsc" FORMAT='+%Y-%m-%d' DATE=$(date $FORMAT) ### LOCK ### echo "Locking $0" if ! lockfile-create -p -r 2 "$0"; then echo "Another backup is running, aborting" exit 49 fi split_date() { echo "$1" | sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\1\n\2\n\3/' } handle_dataset() { DATASET=$1 AUTO_CREATE=$2 D=$3 W=$4 M=$5 Y=$6 PREFIX=$7 if test -z "$PREFIX"; then PREFIX="zsc-" fi if test "!no_prefix!" = "$PREFIX"; then PREFIX="" fi echo "--- $DATASET --- $D $W $M $Y $PREFIX" # Create new snapshot if [ $(zfs list -t snapshot -o name "$DATASET" | grep "$DATE" | head -n1 | wc -l) -eq 0 ]; then echo -e if [ $AUTO_CREATE == "true" ]; then echo -e "Creating snapshot $DATASET@$PREFIX$DATE" zfs snapshot "$DATASET@$PREFIX$DATE" else echo -e "Skip snapshot creation" fi echo -e fi # Delete old snapshots SNAPSHOTS=($(zfs list -t snapshot -o name "$DATASET" | grep "@$PREFIX" | sort -r)) for s in "${SNAPSHOTS[@]}"; do sdate=$(echo "$s" | awk 'match($0, /.+@'"$PREFIX"'(.+)/, a) {print a[1]}') scomp=($(split_date "$sdate") $(date -d "$sdate" "+%u %W")) echo -n "${scomp[3]} ${scomp[4]} | " echo -n "${sdate}: " if [ $D -gt 0 ]; then D=$(( D-1 )) echo "KEEP; D: $D" elif [ $W -gt 0 ] && [ ${scomp[3]#0} -eq 1 ]; then W=$(( W-1 )) echo "KEEP; W: $W" elif [ $M -gt 0 ] && [ ${scomp[3]#0} -eq 1 ] && [ $(( ${scomp[4]#0} % 4 )) -eq 0 ]; then M=$(( M-1 )) echo "KEEP; M: $M" elif [ $Y -gt 0 ] && [ ${scomp[3]#0} -eq 1 ] && [ ${scomp[4]#0} -eq 4 ]; then Y=$(( Y-1 )) echo "KEEP; Y: $Y" else zfs destroy "$s" echo "DISCARD" fi done } cat "$CONFIG_FILE" | while IFS=: read dataset recursive auto_create d w m y prefix; do echo "| ##### Dataset: $dataset Recursive: $recursive Auto create: $auto_create Prefix: $prefix d: $d w: $w m: $m y: $y #####" if [ $recursive = "true" ]; then SUBDATASETS=($(zfs list -o name | grep "$dataset/")) echo -e "| Subdatasets: ${SUBDATASETS[@]}" echo -e '|' for p in "${SUBDATASETS[@]}"; do handle_dataset $p $auto_create $d $w $m $y $prefix | awk '{print "| " $0}' echo -e '|' done fi handle_dataset $dataset $auto_create $d $w $m $y $prefix | awk '{print "| " $0}' echo -e "----------------------------------------------------------------------" done ### UNLOCK ### echo "Unlocking $0" lockfile-remove "$0"