zfs-backup/backup.sh

162 lines
4.1 KiB
Bash
Raw Normal View History

2022-11-19 08:34:22 +00:00
#!/usr/bin/env sh
nodes_file="nodes.txt"
2022-11-19 08:49:50 +00:00
### nodes.txt
2022-11-20 08:33:44 +00:00
# <local hostname> <local ssh port> <this host's root zfs> <this host's user>
# <remote host 1 address> <host 1 ssh port> <host 1 root zfs>
# <remote host 2 address> <host 2 ssh port> <host 2 root zfs>
2022-11-19 08:36:40 +00:00
# ...
datasets_file="datasets.txt"
2022-11-21 01:15:43 +00:00
### datasets.txt
2022-11-19 08:36:40 +00:00
# <dataset 1>
# <dataset 1>/<dataset 1a>
# <dataset 1>/<dataset 1b>
# <dataset 2>/<dataset 2a>
# <dataset 3>
# ...
list_active_datasets()
2022-11-19 08:34:22 +00:00
{
2022-11-21 02:51:03 +00:00
zfs list | tail -n +2 | cut -d' ' -f1|grep ${BG_ROOT}
2022-11-19 08:34:22 +00:00
}
# compare_datasets()
create_datasets() {
# should compare_datasets and only create missing or possibly error.
2022-11-24 03:56:12 +00:00
for dataset in `cat ${datasets_file}`; do
2022-11-24 04:30:42 +00:00
case $dataset in
\#*) continue;;
esac
2022-11-24 03:56:12 +00:00
if [ $BG_TEST_MODE = "TRUE" ]; then
echo zfs create -p ${BG_ROOT}/$dataset
else
zfs create -p ${BG_ROOT}/$dataset
fi
done
}
2022-11-19 08:34:22 +00:00
get_latest_snapshot()
{
zfs list -t snapshot |
2022-11-21 02:51:03 +00:00
grep ${BG_ROOT} |
2022-11-19 08:34:22 +00:00
tail -n1 |
cut -d'@' -f2 |
cut -d' ' -f 1
}
setup_aggregator()
{
create_datasets
if [ $BG_TEST_MODE = "TRUE" ]; then
echo zfs allow -u ${BG_USER} send,snapshot,hold ${BG_ROOT}
else
zfs allow -u ${BG_USER} send,snapshot,hold ${BG_ROOT}
fi
2022-11-19 08:34:22 +00:00
}
setup_mirror()
{
if [ $BG_TEST_MODE = "TRUE" ]; then
echo zfs allow -u ${BG_USER} send,snapshot,hold ${BG_ROOT}
echo zfs allow -u ${BG_USER} \
compression,mountpoint,receive,create,mount ${BG_ROOT}
else
zfs allow -u ${BG_USER} send,snapshot,hold ${BG_ROOT}
zfs allow -u ${BG_USER} \
compression,mountpoint,receive,create,mount ${BG_ROOT}
fi
2022-11-19 08:34:22 +00:00
}
create_snapshot()
{
id="`date -I`-`date +%s`"
2022-11-21 02:51:03 +00:00
if [ $BG_TEST_MODE = "TRUE" ]; then
echo zfs snapshot -r ${BG_ROOT}@${id}
2022-11-21 01:06:47 +00:00
else
2022-11-21 02:51:03 +00:00
zfs snapshot -r ${BG_ROOT}@${id}
2022-11-21 01:06:47 +00:00
fi
2022-11-19 08:34:22 +00:00
}
send_single_snapshot()
{
2022-11-21 02:51:03 +00:00
BG_NEW_SNAPSHOT=`get_latest_snapshot`
tail -n +2 ${nodes_file} > sendnodes.tmp
2022-11-21 02:51:03 +00:00
while read BG_REMOTE_ADDR BG_REMOTE_PORT BG_REMOTE_ROOT BG_REMOTE_USER; do
case $BG_REMOTE_ADDR in
2022-11-20 08:33:44 +00:00
\#*) continue;;
esac
2022-11-21 02:51:03 +00:00
if [ $BG_TEST_MODE = "TRUE" ]; then
echo zfs send -R ${BG_ROOT}@${BG_NEW_SNAPSHOT}
echo ssh -i ~/.ssh/id_rsa -o port=${BG_REMOTE_PORT} \
${BG_REMOTE_USER}@${BG_REMOTE_ADDR} \
zfs receive -sdvu ${BG_REMOTE_ROOT}
2022-11-20 08:33:44 +00:00
else
2022-11-21 02:51:03 +00:00
zfs send -R ${BG_ROOT}@${BG_NEW_SNAPSHOT} |
ssh -i ~/.ssh/id_rsa -o port=${BG_REMOTE_PORT} \
${BG_REMOTE_USER}@${BG_REMOTE_ADDR} \
zfs receive -sdvu ${BG_REMOTE_ROOT}
2022-11-20 08:33:44 +00:00
fi
done < sendnodes.tmp
rm sendnodes.tmp
2022-11-21 02:51:03 +00:00
if [ $BG_TEST_MODE = "TRUE" ]; then
2022-11-20 08:33:44 +00:00
:
else
2022-11-21 02:51:03 +00:00
echo $BG_NEW_SNAPSHOT > "old-snapshot.txt"
2022-11-20 08:33:44 +00:00
fi
2022-11-19 08:34:22 +00:00
}
2022-11-19 08:51:26 +00:00
send_incremental_snapshot()
2022-11-19 08:34:22 +00:00
{
2022-11-21 02:51:03 +00:00
BG_NEW_SNAPSHOT=`get_latest_snapshot`
echo Will send $BG_NEW_SNAPSHOT
#while read BG_REMOTE_ADDR BG_REMOTE_PORT BG_REMOTE_ROOT BG_REMOTE_USER; do
# zfs send -R -i `cat old-snapshot.txt` ${BG_ROOT}@${BG_NEW_SNAPSHOT} |
# ssh -i ~/.ssh/id_rsa -o port=${BG_REMOTE_PORT} \
# ${BG_REMOTE_USER}@${BG_REMOTE_ADDR} \
# zfs receive -sdvu ${BG_REMOTE_ROOT}@${BG_NEW_SNAPSHOT}
2022-11-20 08:33:44 +00:00
#done
2022-11-21 02:51:03 +00:00
echo $BG_NEW_SNAPSHOT > "old-snapshot.txt"
2022-11-19 08:34:22 +00:00
}
2022-11-20 08:33:44 +00:00
################################### MAIN ####################################
### Options
set -- `getopt "tl:" "$@"` || {
echo "Usage: `basename $0` [-tl] [command]" 1>&2
exit 1
}
2022-11-21 02:51:03 +00:00
BG_TEST_MODE=FALSE
2022-11-20 08:33:44 +00:00
while :; do
case "$1" in
-t)
2022-11-21 02:51:03 +00:00
BG_TEST_MODE=TRUE
2022-11-20 08:33:44 +00:00
echo Test mode.
;;
--) shift; break ;;
esac
shift
done
2022-11-21 02:51:03 +00:00
read BG_HOST BG_PORT BG_ROOT BG_USER < ${nodes_file}
2022-11-20 08:33:44 +00:00
if [ ! -f ${nodes_file} ]; then echo "No nodes specified."; exit 2; fi
2022-11-20 08:33:44 +00:00
### Command
case "$1" in
list) list_active_datasets ;;
2022-11-20 08:33:44 +00:00
create) create_snapshot ;;
setup-mirror) setup_mirror ;;
2022-11-24 03:57:57 +00:00
setup-aggregator) setup_aggregator ;;
2022-11-20 08:33:44 +00:00
send)
if [ -f "old-snapshot.txt" ]; then
send_incremental_snapshot
else
send_single_snapshot
fi
;;
esac