-
Hahn Axel (hahn) authoredHahn Axel (hahn) authored
restore.sh 9.02 KiB
#!/bin/bash
# ================================================================================
#
# RESTORE - interactive restore
#
# Restore duplicity backup data to a local directory.
# Please notice: duplicity does not overwrite any dir or file. So the restore
# path is different to the path of the backed up data.
#
# SYNTAX:
# restore.sh [path-to-restore]
#
# path-to-restore - optional
# default: none ... you get an interactive selection of backup sets
#
# --------------------------------------------------------------------------------
# ah - Axel Hahn <axel.hahn@iml.unibe.ch>
# ds - Daniel Schueler <daniel.schueler@iml.unibe.ch>
#
# 2016-11-17 ah,ds v1.0
# 2017-10-11 ah,ds v1.1 added support for duplicity param --ssh-backend
# 2018-08-27 ah,ds v1.2 fix restore target with a given selection; handle '*' placeholder
# 2019-06-05 ah,ds v1.3 add custom cache dir
# 2021-05-19 ah,ds, v2.0 plugin driven
# 2022-10-21 ah v2.1 init vars; shell fixes
# 2024-02-01 ah v2.2 update restore menu
# ================================================================================
# --------------------------------------------------------------------------------
# CONFIG
# --------------------------------------------------------------------------------
# . `dirname $0`/inc_config.sh
. $(dirname $0)/includes/jobhelper.sh || exit 1
. $(dirname $0)/includes/inc_bash.sh || exit 1
# --- load a transfer plugin
STORAGE_BIN=$(_j_getvar ${STORAGEFILE} "bin")
if [ -z "$STORAGE_BIN" ]; then
if ! id -u | grep '^0$'
then
cecho error "ERROR: Maybe you need root permissions to start $0"
else
cecho error "ERROR: missing config bin = ... for file transfer."
fi
exit 1
fi
CFGPREFIX=${STORAGE_BIN}_
. $(dirname $0)/plugins/transfer/$STORAGE_BIN.sh || exit 1
# --- get backend url of backup data
STORAGE_BASEDIR=$(_j_getvar ${STORAGEFILE} "storage")
if [ -z $STORAGE_BASEDIR ]; then
echo "ERROR: missing config for backup target."
echo "There must be an entry storage in ${STORAGEFILE}"
exit 1
fi
# target directory of directory specific repository
STORAGE_TARGETPATH=
PASSPHRASE=$(_j_getvar "${STORAGEFILE}" "passphrase")
# timestamp or snapshot id
RESTORE_ITEM=
# include filter to restore a part of the backup set
RESTORE_FILTER=
# full path of restore data
RESTORE_BASEDIR=$(_j_getvar "${STORAGEFILE}" "restore-path")
RESTORE_TARGETPATH=
# set vars for transfer plugin
t_setVars || exit 1
# ----- Create default command line parameters
export ARGS_DEFAULT
ARGS_DEFAULT="$( t_getParamDefault $1 $2 )"
sFileSshPrivkey=$(_j_getvar "${STORAGEFILE}" "ssh-privatekey")
if [ -n "$sFileSshPrivkey" ]; then
ARGS_DEFAULT="${ARGS_DEFAULT} $( t_getParamSshKey $sFileSshPrivkey )"
fi
# task#3046 - add custom cache dir
sCacheDir=$(_j_getvar "${STORAGEFILE}" "cachedir")
ARGS_DEFAULT="${ARGS_DEFAULT} $( t_getParamCacheDir $sCacheDir )"
# ----- what to restore ...
BACKUP_DIR=
# --------------------------------------------------------------------------------
# FUNCTIONS
# --------------------------------------------------------------------------------
# ----------------------------------------------------------------------
# enter name of directory to restore; menu item
# ----------------------------------------------------------------------
function enterBackupDir(){
h2 "select a directory to be restored"
echo "This is a list of the directories from the backup configuration."
echo "Enter the full path"
echo
echo "Enter the full path; marked entries with (*) do not exist on this machine"
echo
local sDirs="$(j_getDirs2Backup)"
for mydir in $sDirs
do
if [ ! -d "$mydir" ]; then
color error
echo "$mydir (*)"
color reset
else
echo "$mydir"
fi
done
color input
echo -n "[$BACKUP_DIR] >"
color reset
read -r myinput
setBackupDir "${myinput}"
}
# ----------------------------------------------------------------------
# set backup dir .. called when using cli parameter or enterBackupDir
# param string full path of a directory to retore
# ----------------------------------------------------------------------
function setBackupDir(){
if [ ! -z $1 ]; then
sDirs2Backup="$(j_getDirs2Backup)"
bFound=0
for mydir in ${sDirs2Backup}
do
if [ "${mydir}" = "${1}" ]; then
bFound=1
fi
done
if [ $bFound -eq 0 ]; then
color error
echo
echo "WARNING: seems to be wrong ... "
echo "At the moment I restore only known targets."
color reset
# TODO: if we want to retore other backup sets of other servers
# we cannot be as strict
else
BACKUP_DIR=$1
setVars
fi
fi
}
# ----------------------------------------------------------------------
# internal: set variables for target path and backup set
# ----------------------------------------------------------------------
# set backup url and local restore path (based on given backup directory)
function setVars(){
local sSafeName=$(j_getSafename "$BACKUP_DIR")
RESTORE_TARGETPATH="${RESTORE_BASEDIR}/${sSafeName}"
STORAGE_TARGETPATH="$( t_backupDirGetTarget $BACKUP_DIR )"
}
# actions for restore
function doRestore(){
local restorecmd=$( t_restoreDoRestore )
if [ -z "$restorecmd" ]; then
color error
echo "ERROR: There is no restore command ... "
echo "A developer must check t_restoreDoRestore in plugins/transfer/$STORAGE_BIN.sh"
color reset
exit 1
fi
mkdir -p "${RESTORE_TARGETPATH}"
echo "$restorecmd"
color cmd
$restorecmd
fetchrc
color reset
t_rcCheckRestore $myrc
echo
echo
echo Restore is finished.
echo Have look to the output above.
echo "The restore path has $(find ${RESTORE_TARGETPATH} | wc -l) items ($(du -hs ${RESTORE_TARGETPATH} | awk '{ print $1 }'))"
echo
echo " find ${RESTORE_TARGETPATH}"
echo
exit
}
# --------------------------------------------------------------------------------
# MAIN
# --------------------------------------------------------------------------------
# ----- set a directory to restore to have a useful initial point
t_checkRequirements
setBackupDir $1
if [ -z "$BACKUP_DIR" ]; then
enterBackupDir
fi
# ----- menu and loop
while true
do
h1 "Restore :: Menu"
echo " D - directory to restore: $( color cmd ; echo -n $BACKUP_DIR; color reset)"
echo
echo "---------- Restore method 1:"
echo
echo " M - mount backup with fuse"
echo
echo "---------- Restore method 2:"
echo
echo -n " W - time or snapshot ID : $( color cmd ; echo -n $RESTORE_ITEM; color reset)"
test -z "$RESTORE_ITEM" && echo -n " ... set one first"
test -z "$RESTORE_ITEMINFO" || echo -n " ($RESTORE_ITEMINFO)"
echo
echo -n " F - what to restore : $( color cmd ; echo -n $RESTORE_FILTER; color reset)"
test -z "$RESTORE_FILTER" && echo -n "(no filter = restore all files)"
echo
echo
# echo " C - show file changes"
# echo " V - verify"
# echo
echo " R - start restore with $STORAGE_BIN"
echo
echo " restore from : $STORAGE_TARGETPATH" | sed 's#:[^:]*@#:**********@#'
echo " restore to : $( color cmd ; echo -n $RESTORE_TARGETPATH; color reset)"
echo -n " "
if [ -n "$RESTORE_TARGETPATH" ]; then
ls -d "$RESTORE_TARGETPATH" >/dev/null 2>&1
if [ $? -eq 0 ]; then
color error
echo "WARNING: directory already exists! Backup will fail."
color reset
else
echo "OK, it does not exist yet"
fi
else
echo "(not set)"
fi
echo
echo "---------- Other options:"
echo
echo " S - search files"
echo " B - Bash (Shell)"
echo " X - exit"
echo
showPrompt "Select (not case sensitive) --> "
read -r action
echo
case $action in
d|D)
enterBackupDir
;;
w|W)
h2 "Set a time / select a snapshot"
t_restoreDoSelect
;;
c|C)
showFilechanges
;;
m|M)
h2 "Mount backup data"
t_restoreDoMountBackupdata
;;
s|S)
h2 "Search a file"
filefilter=".*"
showPrompt "Regex for filefilter; ${filefilter} for all >"
read -r filefilter
test -z "${filefilter}" || t_restoreDoSearchFile "${filefilter}"
;;
# v|V)
# t_backupDoVerify
# ;;
b|B)
h2 "Shell"
echo "HINT: type exit in the subshell to return to the menu."
echo
export PS1="RESTIC [$(basename $0) \u@\h \w]\$ "
bash --noprofile
;;
f|F)
h2 "Filter restore items"
echo "By default all files will be restored."
echo "You can limit it by setting include rules."
t_restoreDoSetIncludeFilter
;;
r|R)
h2 "Start restore"
doRestore
;;
x|X)
exit 0
;;
*)
echo "Try again"
esac
done
# --------------------------------------------------------------------------------