diff --git a/.idea/.idea.borgScripts.dir/.idea/dictionaries/asif.xml b/.idea/.idea.borgScripts.dir/.idea/dictionaries/asif.xml new file mode 100644 index 0000000..fc63b29 --- /dev/null +++ b/.idea/.idea.borgScripts.dir/.idea/dictionaries/asif.xml @@ -0,0 +1,12 @@ + + + + borgbackup + borghelper + borgvars + listall + makevars + viewarchive + + + \ No newline at end of file diff --git a/.idea/.idea.borgScripts.dir/.idea/indexLayout.xml b/.idea/.idea.borgScripts.dir/.idea/indexLayout.xml new file mode 100644 index 0000000..27ba142 --- /dev/null +++ b/.idea/.idea.borgScripts.dir/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.borgScripts.dir/.idea/riderModule.iml b/.idea/.idea.borgScripts.dir/.idea/riderModule.iml new file mode 100644 index 0000000..1a4e0d9 --- /dev/null +++ b/.idea/.idea.borgScripts.dir/.idea/riderModule.iml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.borgScripts.dir/.idea/vcs.xml b/.idea/.idea.borgScripts.dir/.idea/vcs.xml index d4d4d27..45577ff 100644 --- a/.idea/.idea.borgScripts.dir/.idea/vcs.xml +++ b/.idea/.idea.borgScripts.dir/.idea/vcs.xml @@ -7,4 +7,7 @@ + + + \ No newline at end of file diff --git a/borghelper.sh b/borghelper.sh index ed13a27..a221bf8 100755 --- a/borghelper.sh +++ b/borghelper.sh @@ -15,15 +15,16 @@ trap trapExit 1 2 3 6 ### functions -cleanup () { +cleanup() { # remove borg temp directory, if it exists + # shellcheck disable=SC2154 if [ -d "${borgBaseDir}/tmp" ]; then - if ! rm -rf "${borgBaseDir}/tmp" > /dev/null 2>&1; then + if ! rm -rf "${borgBaseDir}/tmp" >/dev/null 2>&1; then consoleError 3 "Script completed successfully but could not remove temporary directory at '$borgBaseDir/tmp'. Sorry to be messy." fi fi if [ -f "${restorePath}/touch.test" ]; then - if ! rm -f "${restorePath}/touch.test" > /dev/null 2>&1; then + if ! rm -f "${restorePath}/touch.test" >/dev/null 2>&1; then consoleError 5 "Script completed successfully but could not remove test file at '$restorePath/touch.test'. Sorry to be messy." fi fi @@ -37,73 +38,72 @@ consoleError() { scriptHelp() { printf "\n" - textblock "${bold}Usage: borghelper.sh [parameters]${norm}" + textBlock "${bold}Usage: borghelper.sh [parameters]${norm}" printf "\n" - textblock "Simple script to read connection parameters from a flat text file and process borg 'info', 'list' and 'restore' commands without the very long command lines that are required when specifying repo names and passwords, etc." + textBlock "Simple script to read connection parameters from a flat text file and process borg 'info', 'list' and 'restore' commands without the very long command lines that are required when specifying repo names and passwords, etc." printf "\n" - textblock "${magenta}The script has the following parameters:${norm}" + textBlock "${magenta}The script has the following parameters:${norm}" printf "\n" - textblock "${magenta}--- Required Parameters ---${norm}" + textBlock "${magenta}--- Required Parameters ---${norm}" printf "\n" - ptextblock "-v|--vars" - textblock "Path to the .borgvars file from which to read borg connection information. This is not required if run with '--makevars'." + textBlockParams "-v|--vars" + textBlock "Path to the .borgvars file from which to read borg connection information. This is not required if run with '--makevars'." printf "\n" - textblock "${magenta}--- Operation Modes ---${norm}" + textBlock "${magenta}--- Operation Modes ---${norm}" printf "\n" - ptextblock "--makevars" - textblock "Create a sample .borgvars file that you can fill in and use with this script." - ptextblock "-i|--info" - textblock "Get information about a specified borg repo archive. Requires you supply '--archive'." - ptextblock "-l|--list" - textblock "List contents of a specified borg repo archive. Requires you supply '--archive'. You can optionally specify a file/pattern to search for using '--file'." - ptextblock "-la|--list-all" - textblock "List all available archives within the repo specified in your .borgvars file." - ptextblock "-r|--restore" - textblock "Restore the specified borg repo archive/file(s). Requires you supply '--archive'." + textBlockParams "--makevars" + textBlock "Create a sample .borgvars file that you can fill in and use with this script." + textBlockParams "-i|--info" + textBlock "Get information about a specified borg repo archive. Requires you supply '--archive'." + textBlockParams "-l|--list" + textBlock "List contents of a specified borg repo archive. Requires you supply '--archive'. You can optionally specify a file/pattern to search for using '--file'." + textBlockParams "-la|--list-all" + textBlock "List all available archives within the repo specified in your .borgvars file." + textBlockParams "-r|--restore" + textBlock "Restore the specified borg repo archive/file(s). Requires you supply '--archive'." printf "\n" - textblock "${magenta}--- Selector Parameters ---${norm}" + textBlock "${magenta}--- Selector Parameters ---${norm}" printf "\n" - ptextblock "-a|--archive" - textblock "The archive within your borg repo you wish to work with." - ptextblock "--exclude" - textblock "Pattern (python/borg) of files to exclude from a restore operation." - ptextblock "-f|--file" - textblock "Specific file/pattern (python/borg) within an archive for which you want to restore or search. Requires that you supply '--archive'." - ptextblock "-p|--path" - textblock "Path to which you want your archive/files restored. This script will attempt to create the directory for you if it does not already exist." + textBlockParams "-a|--archive" + textBlock "The archive within your borg repo you wish to work with." + textBlockParams "--exclude" + textBlock "Pattern (python/borg) of files to exclude from a restore operation." + textBlockParams "-f|--file" + textBlock "Specific file/pattern (python/borg) within an archive for which you want to restore or search. Requires that you supply '--archive'." + textBlockParams "-p|--path" + textBlock "Path to which you want your archive/files restored. This script will attempt to create the directory for you if it does not already exist." printf "\n" - textblock "${magenta}--- Restore Options ---${norm}" + textBlock "${magenta}--- Restore Options ---${norm}" printf "\n" - ptextblock "--progress" - textblock "Display progress indicator during restore operations. WARNING: This can drastically slow down operations on larger archives!" - ptextblock "--verbose" - textblock "List the individual files being processed during restore operations." + textBlockParams "--progress" + textBlock "Display progress indicator during restore operations. WARNING: This can drastically slow down operations on larger archives!" + textBlockParams "--verbose" + textBlock "List the individual files being processed during restore operations." printf "\n" - textblock "${magenta}--- Other Parameters ---${norm}" + textBlock "${magenta}--- Other Parameters ---${norm}" printf "\n" - ptextblock "-h|-?|--help" - textblock "This help screen." + textBlockParams "-h|-?|--help" + textBlock "This help screen." printf "\n" exit 0 } -textblock() { +textBlock() { printf "%s\n" "$1" | fold -w "$width" -s } -ptextblock() { +textBlockParams() { printf "%s%s%s\n" "$cyan" "$1" "$norm" } -trapExit () { +trapExit() { cleanup printf "%s\nScript execution terminated via signal.\n\n%s" "$err" "$norm" exit 99 } - ### text formatting presets -if command -v tput > /dev/null; then +if command -v tput >/dev/null; then bold=$(tput bold) cyan=$(tput setaf 6) err=$(tput bold)$(tput setaf 1) @@ -119,11 +119,10 @@ else width=80 fi - ### pre-requisites # is user root? -if [ ! "$( id -u )" -eq 0 ]; then +if [ ! "$(id -u)" -eq 0 ]; then consoleError 1 'You must be root to run this script.' fi @@ -135,96 +134,95 @@ fi # process startup parameters while [ $# -gt 0 ]; do case "$1" in - -a|--archive) - # name of backup archive - if [ -z "$2" ]; then - consoleError 1 "Please provide the name of the backup archive you want to work with or use '--list-all' to get a full list." - fi - archiveName="$2" - shift - ;; - --exclude) - # exclude files from restore - if [ -z "$2" ]; then - consoleError 1 "Please provide a list of exclusions in the proper borg format." - fi - exclusions="$2" - shift - ;; - -f|--file) - # specific file/pattern to restore - if [ -z "$2" ]; then - consoleError 1 'Please provide the name of the specific file/pattern for which you want to restore or search.' - fi - fileName="$2" - shift - ;; - -h|-\?|--help) - # display help - scriptHelp - ;; - -i|--info) - # show archive information - operation='info' - ;; - -l|--list) - # list contents of specific backup - operation='viewarchive' - ;; + -a | --archive) + # name of backup archive + if [ -z "$2" ]; then + consoleError 1 "Please provide the name of the backup archive you want to work with or use '--list-all' to get a full list." + fi + archiveName="$2" + shift + ;; + --exclude) + # exclude files from restore + if [ -z "$2" ]; then + consoleError 1 "Please provide a list of exclusions in the proper borg format." + fi + exclusions="$2" + shift + ;; + -f | --file) + # specific file/pattern to restore + if [ -z "$2" ]; then + consoleError 1 'Please provide the name of the specific file/pattern for which you want to restore or search.' + fi + fileName="$2" + shift + ;; + -h | -\? | --help) + # display help + scriptHelp + ;; + -i | --info) + # show archive information + operation='info' + ;; + -l | --list) + # list contents of specific backup + operation='viewarchive' + ;; - -la|--list-all) - # list all backup archives - operation='listall' - ;; - --makevars) - # make a borgvars template file - operation='makevars' - ;; - -p|--path) - # path to restore files - if [ -z "$2" ]; then - consoleError 1 'Please specify a path where you want files restored.' - fi - restorePath="${2%/}" - shift - ;; - --progress) - # show progress - commonOptions="$commonOptions --progress" - ;; - -r|--restore) - # restore archive/file - operation='restore' - ;; - -v|--vars) - # location of borgvars file - if [ -z "$2" ]; then - consoleError 1 'Please provide the path to the file with your borg connection information.' - elif [ ! -f "$2" ]; then - consoleError 1 'The specified borg connection information file does not exist.' - exit 1 - fi - varsFile="$2" - shift - ;; - --verbose) - # display each file being processed - restoreOptions="$restoreOptions --list" - ;; - *) - # invalid option - printf "%s\nUnknown option: %s\n" "$err" "$1" - printf "Use '--help' for valid options.\n\n%s" "$norm" + -la | --list-all) + # list all backup archives + operation='listall' + ;; + --makevars) + # make a borgvars template file + operation='makevars' + ;; + -p | --path) + # path to restore files + if [ -z "$2" ]; then + consoleError 1 'Please specify a path where you want files restored.' + fi + restorePath="${2%/}" + shift + ;; + --progress) + # show progress + commonOptions="$commonOptions --progress" + ;; + -r | --restore) + # restore archive/file + operation='restore' + ;; + -v | --vars) + # location of borgvars file + if [ -z "$2" ]; then + consoleError 1 'Please provide the path to the file with your borg connection information.' + elif [ ! -f "$2" ]; then + consoleError 1 'The specified borg connection information file does not exist.' exit 1 - ;; + fi + varsFile="$2" + shift + ;; + --verbose) + # display each file being processed + restoreOptions="$restoreOptions --list" + ;; + *) + # invalid option + printf "%s\nUnknown option: %s\n" "$err" "$1" + printf "Use '--help' for valid options.\n\n%s" "$norm" + exit 1 + ;; esac shift done - ### process 'makevars' operation if [ "$operation" = 'makevars' ]; then - if ! printf "sshKeyFile=\nborgBaseDir=\nborgRepo=\nborgRepoPassword=\nborgRepoKey=\nborgRemote=\n" > ./sample.borgvars; then + if ! printf "sshKeyFile=\nborgBaseDir=\nborgRepo=\nborgRepoPassword=\nborgRepoKey=\nborgRemote=\n" >./sample.borgvars; then consoleError 4 'Could not write sample borgvars file.' else exit 0 @@ -275,25 +273,25 @@ if [ "$operation" = 'restore' ]; then if [ -d "$restorePath" ]; then # convert to absolute path restorePath=$( - cd "$restorePath" || \ - consoleError 5 'Cannot access specified restore directory.'; \ + cd "$restorePath" || + consoleError 5 'Cannot access specified restore directory.' pwd -P ) - if ! touch "${restorePath}/touch.test" > /dev/null 2>&1; then + if ! touch "${restorePath}/touch.test" >/dev/null 2>&1; then consoleError 5 'Cannot write to specified restore directory.' fi else - if ! mkdir -p "${restorePath}" > /dev/null 2>&1; then + if ! mkdir -p "${restorePath}" >/dev/null 2>&1; then consoleError 5 'Cannot create specified restore directory.' else # convert to absolute path restorePath=$( - cd "$restorePath" || \ - consoleError 5 'Cannot access specified restore directory.'; \ + cd "$restorePath" || + consoleError 5 'Cannot access specified restore directory.' pwd -P ) - if ! touch "${restorePath}/touch.test" > /dev/null 2>&1; then - consoleError 5 'Cannot write to specified restore directory.' + if ! touch "${restorePath}/touch.test" >/dev/null 2>&1; then + consoleError 5 'Cannot write to specified restore directory.' fi fi fi @@ -303,14 +301,16 @@ fi # check if file was provided as a relative or absolute path case "${varsFile}" in - /*) - # absolute path, no need to rewrite variable - . "${varsFile}" - ;; - *) - # relative path, prepend './' to create absolute path - . "./${varsFile}" - ;; +/*) + # absolute path, no need to rewrite variable + # shellcheck disable=SC1090 + . "${varsFile}" + ;; +*) + # relative path, prepend './' to create absolute path + # shellcheck disable=SC1090 + . "./${varsFile}" + ;; esac # verify borg base directory @@ -322,6 +322,7 @@ fi export BORG_BASE_DIR="${borgBaseDir%/}" ## check path to SSH keyfile +# shellcheck disable=SC2154 if [ -z "${sshKeyFile}" ]; then consoleError 2 "$varsFile: 'sshKeyFile' is not specified." elif [ ! -f "${sshKeyFile}" ]; then @@ -330,12 +331,14 @@ fi export BORG_RSH="ssh -i ${sshKeyFile}" # check borg repo connect string +# shellcheck disable=SC2154 if [ -z "${borgRepo}" ]; then consoleError 2 "$varsFile: 'borgRepo' is not specified." fi export BORG_REPO="${borgRepo}" # check borg repo password +# shellcheck disable=SC2154 if [ -n "${borgRepoPassword}" ]; then export BORG_PASSPHRASE="${borgRepoPassword}" elif [ "${borgRepoPassword}" = 'none' ]; then @@ -345,14 +348,15 @@ else fi # check borg keyfile if supplied +# shellcheck disable=SC2154 if [ -n "${borgRepoKey}" ]; then export BORG_KEY_FILE="${borgRepoKey}" fi # export borg remote path, if specified +# shellcheck disable=SC2154 if [ -n "${borgRemote}" ]; then export BORG_REMOTE_PATH="${borgRemote}"; fi - ### create borg temp dir: ## python requires a writable temporary directory when unpacking borg and ## executing commands. This defaults to /tmp but many systems mount /tmp with @@ -367,7 +371,6 @@ if [ ! -d "${borgBaseDir}/tmp" ]; then fi export TMPDIR="${borgBaseDir}/tmp" - ### execute borg operations # info operations @@ -388,29 +391,31 @@ elif [ "$operation" = 'restore' ]; then if [ -z "$fileName" ]; then # restore entire archive if [ "$exclusions" ]; then + # shellcheck disable=SC2086 borg --show-rc ${commonOptions} extract ${restoreOptions} ::"${archiveName}" --exclude "${exclusions}" else + # shellcheck disable=SC2086 borg --show-rc ${commonOptions} extract ${restoreOptions} ::"${archiveName}" fi elif [ "$fileName" ]; then # restore file/pattern if [ "$exclusions" ]; then + # shellcheck disable=SC2086 borg --show-rc ${commonOptions} extract ${restoreOptions} ::"${archiveName}" "${fileName}" --exclude "${exclusions}" else + # shellcheck disable=SC2086 borg --show-rc ${commonOptions} extract ${restoreOptions} ::"${archiveName}" "${fileName}" fi fi fi - ### exit gracefully cleanup exit 0 - ### exit codes # 0: no errors, script completed successfully -# 1: parameter error (missing, non-existant or invalid input) +# 1: parameter error (missing, non-existent or invalid input) # 2: parameter missing/invalid in .borgvars file # 3: could not create/remove borg tmp directory # 4: could not write sample borgvars file (permissions?)