Skip to content

Instantly share code, notes, and snippets.

@msmafra
Last active March 9, 2023 19:33
Show Gist options
  • Save msmafra/ba2d0160ac454973209c00add70eea67 to your computer and use it in GitHub Desktop.
Save msmafra/ba2d0160ac454973209c00add70eea67 to your computer and use it in GitHub Desktop.
btrbk simple wrapper
#!/usr/bin/env bash
#####################################################
# Simple BTRBK Wrapper for using with cron or systemd timers
# https://github.com/digint/btrbk/issues/520
#####################################################
# shellcheck disable=SC1001
LC_ALL=C
LANG=C
VERSION="0.1"
declare SCRIPT_NAME
#declare SCRIPT_FOLDER
# declare CURRENT_USER_BIN
declare MOUNT_POINT
declare DEFAULT_PATH
declare -a CONFIG_FILES
SCRIPT_NAME="$(\basename "${0}")"
#SCRIPT_FOLDER="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
#CURRENT_USER_BIN="${HOME}/.local/bin"
MOUNT_POINT="/btrbk_backups"
DEFAULT_PATH="${HOME}/Projects/rest-o"
CONFIG_FILES=(
"btrbk_timemachine.conf"
)
#################################################
# main
# Runs everything
#################################################
main() {
printf "%s version: %s\n" "${SCRIPT_NAME}" "${VERSION}"
printf "Using %s configuration file(s).\n" "${CONFIG_FILES[*]}"
if [[ "${#}" -ne 0 ]]; then
mount_point_check
case "${1}" in
archive)
btrbk_wrap archive "${2}"
;;
backup)
btrbk_wrap resume "${2}"
;;
fix)
btrbk_wrap clean "${2}"
;;
test)
btrbk_wrap dryrun "${2}"
;;
delete)
btrbk_wrap clean "${2}"
;;
help)
this_help
;;
prune)
btrbk_wrap prune "${2}"
;;
snapshot)
btrbk_wrap snapshot "${2}"
;;
stat)
btrbk_wrap stats "${2}"
;;
usage)
this_usage "${@}"
;;
used)
btrbk_wrap usage "${2}"
;;
space)
check_space
;;
version)
message progress "${SCRIPT_NAME} version: ${VERSION}"
;;
*)
message warn "Parameter unknown."
this_help
exit 1
;;
esac
else
this_help
fi
# trap exit_stage_left ERR 0 SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM
}
exit_stage_left() {
local -i error_code
error_code=$?
if [[ "${error_code}" != 0 ]]; then
printf "Error #%s\n" "${error_code}"
else
printf "All done. Bye!\n"
fi
}
# LOG_FILE="/tmp/$(basename "$0").log"
# readonly LOG_FILE
# info() { printf "[INFO] %s" "$*" | \tee --append "${LOG_FILE}" >&2 ; }
# warning() { printf "[WARNING] %s" "$*" | \tee --append "${LOG_FILE}" >&2 ; }
# error() { printf "[ERROR] %s" "$*" | \tee --append "${LOG_FILE}" >&2 ; }
# fatal() { printf "[FATAL] %s" "$*" | \tee --append "${LOG_FILE}" >&2 ; exit 1 ; }
# _error() {
# printf "${red}!!! %s${reset}\\n" "${*}" 1>&2
# }
# _warn() {
# echo >&2 ":: $*"
# }
# _die() {
# echo >&2 ":: $*"
# exit 1
# }
#######################################
# Check if requirements are met and exits with error if not.
# Arguments: None
# Output: [string]
# list with the missing executables
#######################################
requirements() {
local -a req_execs
local -i execs_found_counter
local -a not_found
execs_found_counter=0
req_execs=(
"awk"
"btrbk"
"btrfs"
"doas"
"grep"
"mount"
"mountpoint"
"sed"
"tee"
)
for re in "${req_execs[@]}"; do
if type -P "${re}" >/dev/null; then
((execs_found_counter += 1))
else
not_found+=("${re}")
fi
done
if [[ "${execs_found_counter}" -eq "${#req_execs[@]}" ]]; then
message progress "Requeriments met. Proceding."
else
message info "Some requirements where not met. %s needs:" "${SCRIPT_NAME}"
for nf in "${not_found[@]}"; do
message bullets "${nf}"
done
exit 1
fi
}
#################################################
# check_space
# Just allows backups + snapshot if destination devices has more than space_alert value of space
# Globals: none
# Arguments: none
# Outputs: nothing
#################################################
check_space() {
# check percentage of occupied space
local ocupied_space
local space_alert
# ocupied_space="$(\df --type=btrfs ${MOUNT_POINT} --output=pcent | \sed --sandbox --quiet '/%/{ n; p }' | \sed --sandbox 's/\%//g' | \awk '{$1=$1};1' | \tee /dev/null 2>&1)"
ocupied_space="$(\doas \btrfs filesystem show --raw /btrbk_backups/ \
| \grep devid \
| \awk -F" " '{printf "%3.0f", (($6*100)/$4) }')"
space_alert="93"
if [[ "${ocupied_space}" -gt ${space_alert} ]]; then
# TODO maybe continue, maybe notify-send
message warn "${ocupied_space// /}% is less than the recommended minimum: ${space_alert// /}%"
exit 1
else
message info "${MOUNT_POINT}'s space used: ${ocupied_space// /}%"
fi
}
#################################################
# check_exist
# check if CONFIG_FILES exist
# Globals: none
# Arguments: none
# Outputs: nothing
#################################################
check_exist() {
# check percentage of occupied space
local -a not_found_list
local -i paths_counter
paths_counter=0
for cf in "${CONFIG_FILES[@]}"; do
((paths_counter += 1))
if [[ -f "${cf}" ]]; then
files_found+=("${cf}")
else
not_found_list+=("${cf}")
fi
done
usage_string="$(for ff in "${files_found[@]}"; do printf "%s " "${ff}"; done)"
printf "%s" "${usage_string[*]}"
}
#################################################
# mount_point_check
# check if the backups' destination is mounted and mounts if not
#################################################
mount_point_check() {
local -i tries
tries=5
# Here I check if mount_point is now mounted.
while ! \mountpoint --quiet --nofollow "${MOUNT_POINT}";do
if [[ "${tries}" -ne 0 ]];then
printf "%s Not mounted. Trying to mount it.\n" "${MOUNT_POINT}"
# mounting the backup mounting point
\doas \mount --verbose "${MOUNT_POINT}"
((tries-=1))
else
exit 1
fi
done
}
#################################################
# btrbk_umount
# Globals: MOUNT_POINT
# Arguments: none
# Outputs: none
#################################################
btrbk_umount() {
# Unmount
echo \doas \umount_exec --verbose "${MOUNT_POINT}"
}
#################################################
# btrbk_wrap
# runs btrbk action using the custom .conf files
# Globals: $1, CONFIG_FILES, DEFAULT_PATH and MOUNT_POINT
# Arguments: none
# Outputs: nothing
#################################################
btrbk_wrap() {
local action
local silent
local used_parameters
local match_parameter
action="${1}"
silent="${2}"
case "${silent}" in
1 | simple)
used_parameters="--format=table --config=${DEFAULT_PATH}"
;;
2 | verbose)
used_parameters="--format=table --progress --verbose --config=${DEFAULT_PATH}"
;;
*)
used_parameters="--quiet --config=${DEFAULT_PATH}"
;;
esac
match_parameter="run|dryrun|snapshot|resume|prune|stats|list|usage"
# Run BTRBK if check_space is true
for cf in "${CONFIG_FILES[@]}"; do
# run btrbk with the default configuration file
#"${btrbk_exec}" --verbose run
message info "Running BTRBK Action: ${action}"
if [[ "${action}" = "archive" ]]; then
message progress "1 full cli being used: btrbk ${action} ${used_parameters}/${cf} / ${MOUNT_POINT}"
# shellcheck disable=SC2086
\doas \btrbk ${action} ${used_parameters}/${cf} / "${MOUNT_POINT}"
elif [[ "${action}" = "clean" ]];then
message progress "2 full cli being used: btrbk ${action} ${used_parameters}/${cf} --wipe"
# shellcheck disable=SC2086
\doas \btrbk ${action} ${used_parameters}/${cf} --wipe
elif [[ "${action}" =~ ${match_parameter} ]];then
message progress "3 full cli being used: btrbk ${action} ${used_parameters}/${cf}"
# shellcheck disable=SC2086
\doas \btrbk ${action} ${used_parameters}/${cf}
else
message warn "Unknown parameters"
fi
done
}
#######################################
# function description
# Globals: None
#
# Arguments: None
#
# Outputs: None
#
#######################################
this_usage() {
local args
local -a usage_array
local usage_string
usage_array=("archive" "backup" "snapshot" "help" "usage" "version")
usage_string="$(for ua in "${usage_array[@]}"; do printf "%s | " "${ua}"; done)"
args=$#
if [[ "${1}" =~ ${usage_array[*]} ]]; then
for ua in "${usage_array[@]}"; do
if [[ "${ua}" =~ ${args} ]]; then
printf "%s" "${ua}"
break
fi
done
else
printf "Usage\n\n%s %s" "${SCRIPT_NAME}" "${usage_string[@]}"
fi
}
#######################################
# function description
# Globals: None
#
# Arguments: None
#
# Outputs: None
#
#######################################
this_help() {
BTRBKOHELP="
Help
archive
Archives using: btrbk archive --config=\"<your config file>\"
backup
Backups using: btrbk run --config=\"<your config file>\"
help
Shows this help
usage
Shows a quick how to use this script
snapshot
Snapshots using: runs \btrbk snapshot --config=\"<your config file>\"
stat
Runs using: btrbk stats --config=\"<your config file>\"
space
Shows currently used space at ${MOUNT_POINT}
version
Shows ${SCRIPT_NAME} version
"
printf "%s" "${BTRBKOHELP}"
}
#######################################
# Prints coloured messages for specific purposes
# Arguments:
# message_type, msg
# Outputs:
# Colored string message based on message_type input
#
# this was inspired by Wimpy's World (Martin Wimpress) deb-get fancy_message function
#######################################
message() {
[ -z "${1}" ] || [ -z "${2}" ] && return
local message_type
local msg
local blue
local red
local purple
local scarlet
local orange
local green
local grey
local cyan
local rst
message_type="${1}"
shift
msg="${1}"
blue="\e[38;5;27m"
lightblue="\e[38;5;24m"
red="\e[38;5;196m"
purple="\e[38;5;57m"
scarlet="\e[38;5;196m"
orange="\e[38;5;208m"
green="\e[38;5;22m"
grey="\e[38;5;251m"
cyan="\e[38;5;39m"
rst="\e[0m"
case ${message_type} in
error) printf "%b[e]%s%b\n" "${red}" "${msg}" "${rst}" | \tee >&2 ;;
fatal) printf "%b[f]%s%b\n" "${scarlet}" "${msg}" "${rst}" | \tee >&2 ;;
info) printf "%b[i] %s%b\n" "${blue}" "${msg}" "${rst}" ;;
bullets) printf " %b-> %s%b\n" "${blue}" "${msg}" "${rst}" ;;
progress) printf "%b[p]%s%b\n" "${lightblue}" "${msg}" "${rst}" ;;
recommend) printf "%b[r]%s%b\n" "${cyan}" "${msg}" "${rst}" ;;
warn) printf "%b[w]%s%b\n" "${orange}" "${msg}" "${rst}" ;;
purle) printf "%b%s%b\n" "${purple}" "${msg}" "${rst}" ;;
grey) printf "%b%s%b\n" "${grey}" "${msg}" "${rst}" ;;
green) printf "%b%s%b\n" "${green}" "${msg}" "${rst}" ;;
*) printf " - ? - %s - ? -\n" "${message_type}" ;;
esac
}
#######################################
# starts main
#######################################
main "${@}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment