ZFS comes with a really nice feature of snapshotting the storage at the point of time.
Snapshots can be taken per data pool or dataset, for more reference we can visit this official documentation sites.
https://docs.oracle.com/cd/E23824_01/html/821-1448/gbciq.html
As a backup of our data is so crucial, ZFS is giving us the opportunity to send snapshots to another server configured with ZFS storage over the network.
This saves already a bunch of money that we might spend on 3rd party backup software.
Since there is a plenty of work to do in order to automate ZFS snapshots and sending them over the network, I have decided to dedicate some of my time to this task and implement it properly via the Bash script.
More reference about sending ZFS snapshot can be found on this website.
https://docs.oracle.com/cd/E18752_01/html/819-5461/gbchx.html

In my case, I have created a dedicated account named zfssnap on both source and destination system and exchanged SSH keys, also zfssnap is in the wheel group with sudo privileges.
The system is also configured to forward all email via postfix null-client to the central email relay.

#!/bin/bash
# Defining variables
sourcepool="mysql_tables"
destinationpool="backup"
destinationdataset="mysql_tables"
host="back-pub"
lockfile="/tmp/zfsbackup-${sourcepool}.lock"
yesterday="$(date -d '1 day ago' +%Y-%m-%d)"
today="$(date +%Y-%m-%d)"
starttime="$(date)"
logfile="/root/zfssnapshot-${today}.log"
domain="domain.com"
recipient1="first.person@${domain}"
recipient2="second.person@${domain}"function send-email() {
sudo mailx -r messenger@"${domain}" -a "${logfile}" -s "ZFS Snapshot status for - ${today}" "${recipient1}" "${recipient2}" > "${logfile}"
# Check if backup is still running
if [ -f "${lockfile}" ];then
echo "Backup still running - FAILED" >> "${logfile}"
send-email
rm -f "${logfile}"
exit 1
else
touch "${lockfile}"
fi
# Check if todays snapshot exist
if
sudo zfs list -H -o name -t snapshot | sort | grep -i "${sourcepool}@${today}" > /dev/null; then
echo "Todays snapshot already exists - ${sourcepool}, skipping." >> "${logfile}"
else
# Create it in case it doesn't exist
echo "Creating todays snapshot for ${sourcepool}" >> "${logfile}"
sudo zfs snapshot "${sourcepool}@${today}"
fi
#Check for yesterday snapshot
if sudo zfs list -H -o name -t snapshot | sort| grep -i "${sourcepool}@${yesterday}" > /dev/null;then
# Calculate the size of snapshot that needs to be sent
DOUBLESIZE=($(sudo zfs send -nv -I "${sourcepool}@${yesterday}" "${sourcepool}@${today}"))
echo "Total size of incremental snapshot is - ${DOUBLESIZE[-1]}" >> "${logfile}"
echo "Sending incremental snapshot streams" >> "${logfile}"
sudo zfs send -R -i "${sourcepool}@${yesterday}" "${sourcepool}@${today}" | ssh ${host} "sudo -u zfssnap "sudo zfs receive ${destinationpool}/${destinationdataset}""
if [ $? -ne 0 ]; then
echo "Sending incremental snapshot streams FAILED." >> "${logfile}"
else
echo "Sending incremental snapshot streams COMPLETED." >> "${logfile}"
fi
# If not found, send only todays snapshot
else
# Calculate the size of snapshot that needs to be sent
SINGLESIZE=($(zfs send -nv "${sourcepool}@${today}"))
echo "Total size of todays snapshot is - ${SINGLESIZE[-1]}" >> "${logfile}"
echo "Sending todays snapshot only" >> "${logfile}" >> "${logfile}"
sudo zfs send "${sourcepool}@${today}" | ssh ${host} "sudo -u zfssnap "sudo zfs receive "${destinationpool}/${destinationdataset}"""
if [ $? -ne 0 ]; then
echo "Sending todays snapshot FAILED." >> "${logfile}"
else
echo "Sending todays snapshot COMPLETED." >> "${logfile}"
fi
fi
# Perform snapshot cleanup
OLDSNAPS=$(ssh ${host} "sudo -u zfssnap "sudo zfs list -t snapshot -o name | grep ${destinationpool}/${destinationdataset} | tac | tail -n2"")
for snap in $OLDSNAPS; do
echo "Snapshot ${snap} is gonna be removed from target system." >> "${logfile}"
ssh ${host} "sudo -u zfssnap "sudo zfs destroy ${snap}""
done
# Remove lock file once completed
rm -f "${lockfile}"
# Send the log via email
send-email && rm -f "${logfile}"
exit 0