Fuente:
El autor de este sencillo e ingenioso guión es iceflatline. Contiene algunas modificaciones para adaptarlo a este laboratorio
https://gnulinuxcodigo.blogspot.com/2025/03/crear-particiones-en-disco-duro-usb-con.html
Conjuntos de datos zbackup
carlos@tormenta:~ % zfs list -r zbackup | grep "/zbackup*" zbackup 48.9G 1.71T 4.86M /zbackup zbackup/solaris 40.8G 1.71T 96K /zbackup/solaris zbackup/solaris/home 40.8G 1.71T 96K /zbackup/home zbackup/solaris/home/carlos 40.8G 1.71T 39.9G /zbackup/home/carlos zbackup/tormenta-confiles 800K 1.71T 800K /zbackup/tormenta-confiles zbackup/usr 8.16G 1.71T 104K /zbackup/usr zbackup/usr/backup 7.80G 1.71T 104K /zbackup/usr/backup zbackup/usr/backup/docs 7.80G 1.71T 7.80G /zbackup/usr/backup/docs zbackup/usr/home 368M 1.71T 132M /zbackup/usr/home
#!/bin/sh
### BEGIN INFO
# PROVIDE:
# REQUIRE:
# KEYWORD:
# Description:
# This script is used to replicate incremental zfs snapshots daily from one
# pool/dataset(s) to another using ZFS send and receive.
# The number of snapshots to retain is defined in the variable retention.
# Note that an initial full snapshot must be created and sent to destination
# before this script can be successfully used.
# Author: iceflatline <iceflatline@gmail.com>
#
# OPTIONS:
# -R: Generate replication stream recursively
# -i: Generate incremental stream
# -v: Be verbose
# -u: Do not mount received stream,
# -d: Use the full sent snapshot path without the first element (without pool
# name) to determine the name of the new snapshot
# -F: Destroy snapshots and file systems that do not exist on the sending side.
### END INFO
### INICIO DEL GUION
# Estas variables se nombran primero porque están anidadas en otras variables.
snap_prefix=snap
retention=30
# Se necesitan rutas completas a estas utilidades al ejecutar el script desde
# cron.
date=/bin/date
grep=/usr/bin/grep
sed=/usr/bin/sed
sort=/usr/bin/sort
xargs=/usr/bin/xargs
zfs=/sbin/zfs
src_0="zroot/home"
dst_0="zbackup/solaris"
host="root@192.168.88.160"
today="$snap_prefix-`date +%Y%m%d`"
yesterday="$snap_prefix-`date -v -1d +%Y%m%d`"
snap_today="$src_0@$today"
snap_yesterday="$src_0@$yesterday"
snap_old=`$zfs list -t snapshot -o name | $grep "$src_0@$snap_prefix-*" | \
$sort -r | $sed 1,${retention}d | $sort | $xargs -n 1`
log=/home/carlos/cronlog
# snap_old_dst_0 lista las instantaneas > retention en el pool destino zbackup
dst_0_old="zbackup/solaris"
snap_old_dst_0=`ssh $host $zfs list -t snapshot -o name | \
$grep "$dst_0_old@$snap_prefix*" | $sort -r | $sed 1,${retention}d | $sort \
| $xargs -n 1`
# Crea una línea en blanco entre la entrada de registro anterior y esta
echo >> $log
# Imprimir el nombre del script.
echo "zfsrep.sh" >> $log
# Imprime la fecha de hoy
$date >> $log
# Crea una linea en blanco
echo >> $log
# Busca la instantánea de hoy y, si no la encuentras, créala.
if $zfs list -H -o name -t snapshot | $sort | $grep "$snap_today$" > \
/dev/null
then
echo "La instantánea de hoy '$snap_today' ya existe." >> $log
else
echo "Tomando la instantánea de hoy: $snap_today" >> $log
$zfs snapshot -r $snap_today >> $log 2>&1
fi
echo >> $log
# Busque la instantánea de ayer y, si la encuentra, realice una replicación
# incremental; de lo contrario, imprima un mensaje de error
if $zfs list -H -o name -t snapshot | $sort | $grep "$snap_yesterday$" > \
/dev/null
then
echo "La instantánea de ayer '$snap_yesterday' existe. Continuando con
# la replicacion..." >> $log
$zfs send -R -i $snap_yesterday $snap_today | ssh $host $zfs receive \
-vudF $dst_0 >> $log 2>&1
echo >> $log
echo "Replicacion completada." >> $log
else
echo "Error: Replicacion no completada. Falta la instantánea de ayer." \
>> $log
fi
echo >> $log
# Eliminar instantáneas más antiguas que el valor asignado a retention.
echo "Intentando destruir instantáneas antiguas $src_0..." >> $log
if [ -n "$snap_old" ]
then
echo "Destruyendo las siguientes instantáneas antiguas:" >> $log
echo "$snap_old" >> $log
$zfs list -t snapshot -o name | $grep "$src_0@$snap_prefix*" | \
$sort -r | $sed 1,${retention}d | $sort | $xargs -n 1 $zfs destroy -r >> \
$log 2>&1
else
echo "No se pudo encontrar ninguna instantánea para destruir." >> $log
fi
echo >> $log
# Eliminar instantáneas más antiguas que el valor asignado a retention.
echo "Intentando destruir instantáneas antiguas $dst_0..." >> $log
if [ -n "$snap_old_dst_0" ]
then
snap_remoto="zbackup/solaris/home"
echo "Destruyendo las siguientes instantáneas antiguas:" >> $log
echo "$snap_old_dst_0" >> $log
ssh $host $zfs list -t snapshot -o name | $grep \
"$snap_remoto@$snap_prefix-*" | $sort -r | $sed 1,${retention}d | \
$sort | $xargs -n 1 $zfs destroy -r >> $log 2>&1
else
echo "No se pudo encontrar ninguna instantánea para destruir." >> $log
fi
# Marcar el fin del script con un delimitador.
echo "**********" >> $log
### FIN DEL SCRIPT
Luego, agregue una tarea a la tabla cron bajo la cuenta del usuario. El script se ejecuta todos los días a las 22:00 (hora local):
# Ejecuta script backup cada día a las 22:00 0 22 * * * /home/carlos/bin/zfsrep.sh
Las entradas del archivo /home/carlos/cronlog se verán así:
********** zfsrep.sh Tue Apr 15 09:45:19 CEST 2025 Tomando la instantánea de hoy: zroot/home@snap-20250415 La instantánea de ayer 'zroot/home@snap-20250414' existe. Continuando con la replicacion... receiving incremental stream of zroot/home@snap-20250415 into zbackup/solaris/home@snap-20250415 received 312B stream in 0.91 seconds (341B/sec) receiving incremental stream of zroot/home/carlos@snap-20250415 into zbackup/solaris/home/carlos@snap-20250415 received 16.3M stream in 7.07 seconds (2.30M/sec) Replicacion completada. Intentando destruir instantáneas antiguas zroot/home... Destruyendo las siguientes instantáneas antiguas: zroot/home@snap-20250327 Intentando destruir instantáneas antiguas zbackup/solaris... No se pudo encontrar ninguna instantánea para destruir.FreeBSD es genial!.




