Skip to content
Snippets Groups Projects
Select Git revision
  • cd1687ee3b3d981dd37fa6512addc2d71118e50a
  • master default protected
  • 7771-harden-postgres-backup
  • pgsql-dump-with-snapshots
  • update-colors
  • update-docs-css
  • usb-repair-stick
  • desktop-notification
  • 7000-corrections
  • db-detector
10 results

inc_bash.sh

Blame
  • restic.sh 11.86 KiB
    #!/bin/bash
    # ================================================================================
    #
    # TRANSFER :: PLUGIN - TEMPLATE
    #
    # this script will be included in ../../transfer.sh
    #
    # --------------------------------------------------------------------------------
    # ah - Axel Hahn <axel.hahn@iml.unibe.ch>
    # 2021-05-19  ah    v0.0   INIT ... WIP
    # 2022-01-06  ah    v0.0   added support for Repository with REST and authentication 
    # ================================================================================
    
    # --------------------------------------------------------------------------------
    # INIT
    # --------------------------------------------------------------------------------
    
    
        function t_checkRequirements(){
            j_requireBinary "restic"
            j_requireUser "root"
        }
    
        function t_setVars(){
            export RESTIC_PASSWORD=$PASSPHRASE
    
            # if we set RESTIC_REPOSITORY then "-r TARGET" is not 
            # needed in restic commands
    
            # TODO: for restic with https and auth - remove the host in the path
            local _target=$( j_getFullTarget )
            echo ${_target} | grep "https.*@" >/dev/null
            if [ $? -eq 0 ]; then
                local _host=$( hostname -f )
                _target=$( echo $_target | sed "s#${_host}/##" )
            fi
    
            export RESTIC_REPOSITORY=$_target
    
            # WORKAROUND for bug while writing on a SMB target
            export GODEBUG="asyncpreemptoff=1"
    
            RESTORE_ITEM=latest
            RESTIC_MOUNTPOINT=$( _j_getvar ${STORAGEFILE} "${CFGPREFIX}mountpoint" )
        }
    
    # --------------------------------------------------------------------------------
    # GENERATE PARAMS :: ALL DIRS
    # --------------------------------------------------------------------------------
    
        # return a string with default params
        # param  string  param1 of transfer.sh; one of full|inc|auto
        # param  string  param2 of transfer.sh; for auto: date i.e. 3M for 3 monthes
        function t_getParamDefault(){
            # verbose to see more details
            echo -n --verbose=$( _j_getvar ${STORAGEFILE} "${CFGPREFIX}verbose" )
    
        }
        # return a string with backup parameters that will be added to defaults
        function t_getParamBackup(){
            local _tag
            local _nocacheFlag
    
            # tagging
            _tag=$( _j_getvar ${STORAGEFILE} "${CFGPREFIX}tag" )
            if [ "$_tag" != "" ]; then
                echo -n "--tag $_tag "
            fi
    
            # no cache ... to create smaller local cache dirs, but backup 3 times slower 
            _nocacheFlag=$( _j_getvar ${STORAGEFILE} "${CFGPREFIX}nocache" )
            if [ "$_nocacheFlag" != "" ] && [ "$_nocacheFlag" != "0" ] && [ "$_nocacheFlag" != "false" ]; then
                echo -n "--no-cache "
            fi
        }
    
        # return a cli parameter for a single exlude directory
        # param  string  cache directory for local index files
        function t_getParamCacheDir(){
            if [ ! -z "$1" ]; then
                local sCacheDir="$1"
                if [ ! -d $sCacheDir ]; then
                    mkdir -p $sCacheDir
                    chmod 750 $sCacheDir
                fi
                echo --cache-dir $sCacheDir
            fi
        }
    
        # return a cli parameter for a single exlude directory
        # param  string  exlude pattern
        function t_getParamExlude(){
            test -z "$1" || echo --exclude "'"$*"'"
        }
        # return a cli parameter for a single exlude directory
        # param  string  exlude pattern
        function t_getParamInlude(){
            test -z "$1" || echo --include "'"$*"'"
        }
    
        # return a cli parameter to use an ssh keyfile
        # param  string  filename if ssh private key file
        function t_getParamSshKey(){
            if [ ! -z "$1" ]; then
                echo $STORAGE_BASEDIR | grep -E "^(scp|sftp|rsync):" >/dev/null
                if [ $? -eq 0 ]; then
                    # scp://backup@storage.example.com//netshare/backup/one
                    #       ^^^^^^^^^^^^^^^^^^^^^^^^^^
                    #       sshtarget fetches user@host ... if protocol matches
                    local sshtarget=$( echo $STORAGE_BASEDIR | cut -f 3 -d '/' )
                    echo -o sftp.command="'"ssh -i ${1} ${sshtarget} -s sftp"'"
                fi
            fi
        }
    
    # --------------------------------------------------------------------------------
    # BACKUP ACTIONS :: TRANSFER
    # --------------------------------------------------------------------------------
        # pre backup actions
        # uses global vars from ../../transfer.sh
        # function t_backupDoPreTasks(){
        function t_backupDoPreTasks(){
    
            local _mycmd="restic init ${ARGS_DEFAULT}"
            echo $_mycmd
            color cmd 
            eval $_mycmd
            local _myrc=$?
            color reset
    
            # detect return code ... do not abort on any error.
            t_rcCheckInit $_myrc
    
        }
    
    
        # post backup actions
        # uses global vars from ../../transfer.sh
        function t_backupDoPostTasks(){
    
            echo "--- UNLOCK ... just in case :-)" 
            echo restic unlock ${ARGS_DEFAULT}
            color cmd
            eval restic unlock ${ARGS_DEFAULT}
            color reset
            echo
    
            echo "--- PRUNE"
            local _tag=$( _j_getvar ${STORAGEFILE} "${CFGPREFIX}tag")
            
            local _mycmd="restic forget \
              ${ARGS_DEFAULT} \
              --tag $_tag \
              --group-by paths,tags \
              --cleanup-cache"
    
            local _keep
            for mykeep in last hourly daily weekly monthly yearly
            do
                _keep=$( _j_getvar "${STORAGEFILE}" "${CFGPREFIX}keep-${mykeep}")
                if [ -n "$_keep" ]; then
                    _mycmd="${_mycmd} --keep-${mykeep} ${_keep}"
                fi
            done
    
            echo $_mycmd
            sleep 3
            color cmd 
            eval $_mycmd
            local _myrc=$?
            color reset
    
            t_rcCheckCleanup $_myrc
            echo
        }
    
    # --------------------------------------------------------------------------------
    # BACKUP ACTIONS :: SINGLE DIR
    # --------------------------------------------------------------------------------
    
        # get target url/ directory
        # param  string  directory to backup
        function t_backupDirGetTarget(){
            # directory based target
            # j_getFullTarget "$1"
            # for host based backup target - remove param:
            j_getFullTarget ""
        }
    
        function t_backupDirGetCmdBackup(){
            echo eval restic backup ${ARGS_DEFAULT} ${ARGS_BACKUP} ${mydir}
        }
    
        # pre backup actions
        # uses global vars from ../../transfer.sh
        function t_backupDirDoPreTasks(){
            echo "Nothing to do."
        }
    
    
        # post backup actions
        # uses global vars from ../../transfer.sh
        function t_backupDirDoPostTasks(){
            echo "--- SHOW CHANGES between last 2 snapshots" 
            local _data
            local _snapshotLast
            local _snapshotNow
    
            # get list of snapshots and filter the lines with a date YYYY-MM-DD
            _data=$( t_restoreDoShowVolumes | grep "[12][0-9][0-9][0-1]-[0-2][0-9]-[0-3][0-9]" | tail -5 )
            echo "..."
            echo "$_data"
    
            _snapshotLast=$( echo "$_data" | tail -2 | head -1 | cut -f 1 -d " ")
            _snapshotNow=$(  echo "$_data" | tail -1           | cut -f 1 -d " ")
    
            if [ "${_snapshotLast}" = "${_snapshotNow}" ]; then
                echo "This was the initial (full) Backup"
            else
                color cmd
                restic diff "${_snapshotLast}" "${_snapshotNow}"
                color reset
            fi
            echo
    
        }
    
    # --------------------------------------------------------------------------------
    # RESTORE
    # --------------------------------------------------------------------------------
    
        # show stored volumes on backup repository
        # used in restore; directory param is checked before
        # param  string  name of backup dir, i.e. /etc
        function t_restoreDoShowVolumes(){
            eval restic snapshots ${ARGS_DEFAULT} --path ${BACKUP_DIR}
        }
    
        # select a snapshot to restore from
        function t_restoreDoSelect(){
            local _selid=
            echo "--- Existing snapshots:"
            color cmd
            t_restoreDoShowVolumes
            color reset
            showPrompt "ID of the snapshot or \"latest\" to restore from [${RESTORE_ITEM}] >"
            read _selid
            test -z "$_selid" && _selid=${RESTORE_ITEM}
            RESTORE_ITEM=${_selid}
    
            test "$RESTORE_ITEM" = "latest" && RESTORE_ITEMINFO="automatic value"
            test "$RESTORE_ITEM" = "latest" || RESTORE_ITEMINFO=$( t_restoreDoShowVolumes | grep "^${RESTORE_ITEM} " | awk '{ print $2 " " $3} ' )
    
            if [ -z "${RESTORE_ITEMINFO}" ]; then
                color error
                echo ERROR: A napshot ID \"${_selid}\" does not exist.
                RESTORE_ITEM=latest
                color reset
            fi
            echo using \"${RESTORE_ITEM}\"
            echo
        }
    
        # set a filter to reduce count of files to restore
        function t_restoreDoSetIncludeFilter(){
            local _inc=
            echo "You can enter ..."
            echo "  - a single directory name anywhere in the folderstructure"
            echo "  - a filename without path"
            echo "  - a filemask"
            showPrompt "Include >"
            read _inc
            RESTORE_FILTER="$( t_getParamInlude "${_inc}" )"
            echo using parameter \"${RESTORE_FILTER}\"
            echo
        }
        # show stored volumes on backup repository
        # used in restore; directory param is checked before
        # param  string  name of backup dir, i.e. /etc
        function t_restoreDoRestore(){
            echo "eval restic restore ${ARGS_DEFAULT} --path ${BACKUP_DIR} --target ${RESTORE_TARGETPATH} ${RESTORE_FILTER} ${RESTORE_ITEM}"
        }
    
        # Mount backup data
        # see "restic help mount"
        function t_restoreDoMountBackupdata(){
            local _cmd=
            echo "HINT: This feature requires fuse. It works with root on UNIX/ LINUX platforms - not on MS Windows."
            echo "      It can mount a single directory and shows all snapshots (not only [$RESTORE_ITEM])."
            echo
            if [ -z "$RESTIC_MOUNTPOINT" ]; then
                color error
                echo "ERROR: no mountpoint was set in ${STORAGEFILE}; example: restic_mountpoint = /mnt/restore"
                color reset
            else
                j_requireUser "root"
                test -d "$RESTIC_MOUNTPOINT" || mkdir -p $RESTIC_MOUNTPOINT
                _cmd="restic mount ${ARGS_DEFAULT} $RESTIC_MOUNTPOINT"
                test -z "${BACKUP_DIR}" || _cmd="restic mount ${ARGS_DEFAULT} --path ${BACKUP_DIR} $RESTIC_MOUNTPOINT"
                echo $_cmd
                color cmd
                eval $_cmd
                color reset
            fi
        }
    
        # search a file in the given snapshot and backup dir
        # param  string  regex to filter
        function t_restoreDoSearchFile(){
            eval restic ls ${ARGS_DEFAULT} --path "${BACKUP_DIR}" ${RESTORE_ITEM} | grep -E "$1"
        }
    
    # --------------------------------------------------------------------------------
    # VERIFY RETURNCODES
    # --------------------------------------------------------------------------------
    
        # init repository
        function t_rcCheckInit(){
            case $1 in
                0) color ok;      echo "OK - the repository was created." ;;
                1) color warning; echo "You can ignore the error if the repository was initialized already." ;;
                *) color error;   echo "Verify output above - returncode of restic init was $1" ;;
            esac
            color reset
        }
        # backup files
        function t_rcCheckBackup(){
            case $1 in
                0) color ok;      echo "OK" ;;
                1) color error;   echo "Unable to connect with restic repository." ;;
                *) color error;   echo "Backup error - returncode was $1" ;;
            esac
            color reset
        }
    
        # repository cleanup
        function t_rcCheckCleanup(){
            case $1 in
                0) color ok;      echo "OK" ;;
                *) color error;   echo "Cleanup error - returncode was $1" ;;
            esac
            color reset
        }
    
        # restore files
        function t_rcCheckRestore(){
            case $1 in
                0) color ok;      echo "OK" ;;
                *) color error;   echo "Restore error - returncode was $1" ;;
            esac
            color reset
        }
    
    # --------------------------------------------------------------------------------