Last active
January 21, 2020 23:57
-
-
Save MarcusWichelmann/16d2b9560ad31c99ba8d9c9015ae6e7b to your computer and use it in GitHub Desktop.
Simple script for replication of single datasets over SSH with zfs send/receive
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Source pool or dataset | |
| SOURCE=Storage | |
| # Target location on remote machine | |
| # Note: Ensure all datasets in there are not mounted, otherwise the user on the remote machine needs to have unmount permissions. | |
| TARGET=Storage/Backups/Some-Server | |
| # Datasets to be backed up (relative to source) | |
| DATASETS=(Data) | |
| # Command for ssh connection to remote machine | |
| SSH_COMMAND="ssh -i /some/directory/id_rsa [email protected]" | |
| # Error handling | |
| failure() | |
| { | |
| echo "An error occured. Exiting." | |
| trap : 0 | |
| exit 1 | |
| } | |
| trap 'failure' 0 | |
| set -e | |
| # Backup datasets | |
| for dataset in "${DATASETS[@]}" | |
| do | |
| source_dataset="$SOURCE/$dataset" | |
| target_dataset="$TARGET/$dataset" | |
| # Analyze source dataset | |
| first_source_snap=$(zfs list -t snapshot -o name -s creation -r "$source_dataset" | grep "^$source_dataset@" | head -1 | cut -d '@' -f2 ; exit "${PIPESTATUS[0]}") | |
| last_source_snap=$(zfs list -t snapshot -o name -s creation -r "$source_dataset" | grep "^$source_dataset@" | tail -1 | cut -d '@' -f2 ; exit "${PIPESTATUS[0]}") | |
| # Backups are not possible when no snapshots exist | |
| if [[ -z "$first_source_snap" || -z "$last_source_snap" ]] | |
| then | |
| echo "No snapshots in source '$source_dataset'. Consider setting up zfs-auto-snapshot." | |
| failure | |
| fi | |
| # Analyze remote dataset | |
| first_target_snap=$($SSH_COMMAND zfs list -t snapshot -o name -s creation -r "$target_dataset" | grep "^$target_dataset@" | head -1 | cut -d '@' -f2 ; exit "${PIPESTATUS[0]}") | |
| last_target_snap=$($SSH_COMMAND zfs list -t snapshot -o name -s creation -r "$target_dataset" | grep "^$target_dataset@" | tail -1 | cut -d '@' -f2 ; exit "${PIPESTATUS[0]}") | |
| echo "### Backing up: $source_dataset ($first_source_snap - $last_source_snap) ===> $target_dataset (${first_target_snap:-none} - ${last_target_snap:-none})"; | |
| # It's backup time! | |
| if [[ -z "$last_target_snap" ]] | |
| then | |
| # Send first snapshot to initialize the target | |
| echo "### Target dataset has no snapshots. Sending initial snapshot before starting incremental backups..." | |
| zfs send -v "$source_dataset@$first_source_snap" | gzip --fast | mbuffer -s 128k -m 500M -q | $SSH_COMMAND "gzcat | zfs recv -F $target_dataset" | |
| fi | |
| zfs send -vI "${last_target_snap:-$first_source_snap}" "$source_dataset@$last_source_snap" | gzip --fast | mbuffer -s 128k -m 500M -q | $SSH_COMMAND "gzcat | zfs recv -F $target_dataset" | |
| echo "### Done: $source_dataset"; | |
| done | |
| trap : 0 | |
| echo "Done." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment