Last active
March 9, 2023 19:33
-
-
Save msmafra/ba2d0160ac454973209c00add70eea67 to your computer and use it in GitHub Desktop.
btrbk simple wrapper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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