From b1c22eef0689a84c29ccbee2464b16818e5d8c6a Mon Sep 17 00:00:00 2001 From: Max Christian Pohle Date: Sun, 3 Nov 2019 22:06:34 +0100 Subject: Added script to flatten a dataset hierachy --- zfs-flatten.sh | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 zfs-flatten.sh diff --git a/zfs-flatten.sh b/zfs-flatten.sh new file mode 100644 index 0000000..179048c --- /dev/null +++ b/zfs-flatten.sh @@ -0,0 +1,67 @@ +DATASET_ROOT=$1 +DATASET_TARGET=$2 + +MOUNTPOINT_TARGET=$(zfs get -H mountpoint -o value $DATASET_TARGET) + +if ! test -d "$MOUNTPOINT_TARGET"; then + echo "Please run this program with a source and a target dataset name as arguments" + echo "e.g. $0 zpool/dataset1 zpool/dataset2" + exit +fi + +# make sure, that ctrl-c also works in the inner loops +trap exit INT + +# recursively contains all snapshot names (the part after the @) from root on, sorted and only once +SNAPSHOTS=$(zfs list -H -r $DATASET_ROOT -oname -tsnap | cut -d@ -f2 | sort | uniq) +DATASETS=$(zfs list -H -r $DATASET_ROOT -oname -t filesystem) + +echo "We are going to flatten the hierachy of this dataset:" +printf " %s\n" $DATASETS +echo "into the dataset with the name:" +echo " $DATASET_TARGET" +echo "mounted under:" +echo " $MOUNTPOINT_TARGET" +echo "" +echo "You have 10 seconds to abort this with CTRL-C" +sleep 10 + +for SNAPSHOT in $SNAPSHOTS; do + echo "" + echo "" + echo "===========================" + echo "Next snapshot is: $SNAPSHOT" + echo "===========================" + + for DATASET in $DATASETS; do + + MOUNTPOINT=$(zfs get -H mountpoint -o value $DATASET) + + if [[ $MOUNTPOINT == "legacy" ]]; then + MOUNTPOINT=$(findmnt -n -o target $DATASET) + if test -d $MOUNTPOINT; then + >&2 echo "Dataset has a legacy mountpoint, but was not found in the fstab: $DATASET" + continue + fi + fi + + if [[ $MOUNTPOINT == "-" ]]; then + >&2 echo "Dataset does not have a mount point or is a vdev: $DATASET" + continue + fi + + SNAPDIR=$(realpath $MOUNTPOINT/.zfs/snapshot/$SNAPSHOT) + if test -d $SNAPDIR; then + TARGET_DIR="$(realpath $DATASET_TARGET)$(realpath $MOUNTPOINT)" + mkdir -p "$TARGET_DIR" + echo rsync --info=stats3 -a "$SNAPDIR/" "$TARGET_DIR/" + if ! rsync --info=stats3 -a "$SNAPDIR/" "$TARGET_DIR/" ; then + >&2 echo "rsync could not entirely copy from $SNAPDIR to $DATASET_TARGET" + fi + fi + done + NEW_SNAPSHOT="$DATASET_TARGET@$SNAPSHOT" + echo "Files copied, creating snapshot: $NEW_SNAPSHOT" + zfs snap $NEW_SNAPSHOT +done + -- cgit v1.2.3