added lib.sh and updated restic-backup.sh to v0.2.0
This commit is contained in:
parent
98ee8363ae
commit
b3e12fa198
|
@ -0,0 +1,134 @@
|
||||||
|
# This file is meant to be sourced by another script,
|
||||||
|
# it contains only BASH functions and global variables.
|
||||||
|
|
||||||
|
|
||||||
|
## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
|
||||||
|
## ##
|
||||||
|
## lib.sh ##
|
||||||
|
## ##
|
||||||
|
## Library for my personal BASH scripts ##
|
||||||
|
## ##
|
||||||
|
## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
## Information
|
||||||
|
##
|
||||||
|
|
||||||
|
LIB_NAME="lib.sh"
|
||||||
|
LIB_DESCRIPTION="Library for my personal BASH scripts"
|
||||||
|
LIB_VERSION="0.1.0"
|
||||||
|
LIB_AUTHOR="david@socialnerds.org"
|
||||||
|
LIB_LICENSE="MIT"
|
||||||
|
LIB_WEBSITE="https://git.socialnerds.org/david/scripts"
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
## Variables
|
||||||
|
##
|
||||||
|
|
||||||
|
# Reset text formatting
|
||||||
|
LIB_CLEAR="\e[0m"
|
||||||
|
|
||||||
|
# Text settings
|
||||||
|
LIB_BOLD="\e[1m"
|
||||||
|
LIB_UNDERLINE="\e[4m"
|
||||||
|
|
||||||
|
# Text color
|
||||||
|
LIB_RED="\e[31m"
|
||||||
|
LIB_GREEN="\e[32m"
|
||||||
|
LIB_YELLOW="\e[33m"
|
||||||
|
LIB_BLUE="\e[34m"
|
||||||
|
LIB_MAGENTA="\e[35m"
|
||||||
|
LIB_CYAN="\e[36m"
|
||||||
|
LIB_LIGHTGREY="\e[37m"
|
||||||
|
|
||||||
|
# Text color with bold font
|
||||||
|
LIB_RED_BOLD="\e[1;31m"
|
||||||
|
LIB_GREEN_BOLD="\e[1;32m"
|
||||||
|
LIB_YELLOW_BOLD="\e[1;33m"
|
||||||
|
LIB_BLUE_BOLD="\e[1;34m"
|
||||||
|
LIB_MAGENTA_BOLD="\e[1;35m"
|
||||||
|
LIB_CYAN_BOLD="\e[1;36m"
|
||||||
|
LIB_LIGHTGREY_BOLD="\e[1;37m"
|
||||||
|
|
||||||
|
# Background color
|
||||||
|
LIB_RED_BG="\e[41m"
|
||||||
|
LIB_GREEN_BG="\e[42m"
|
||||||
|
LIB_YELLOW_BG="\e[43m"
|
||||||
|
LIB_BLUE_BG="\e[44m"
|
||||||
|
LIB_MAGENTA_BG="\e[45m"
|
||||||
|
LIB_CYAN_BG="\e[46m"
|
||||||
|
LIB_LIGHTGREY_BG="\e[47m"
|
||||||
|
|
||||||
|
# Background color with bold font
|
||||||
|
LIB_RED_BG_BOLD="\e[1;41m"
|
||||||
|
LIB_GREEN_BG_BOLD="\e[1;42m"
|
||||||
|
LIB_YELLOW_BG_BOLD="\e[1;43m"
|
||||||
|
LIB_BLUE_BG_BOLD="\e[1;44m"
|
||||||
|
LIB_MAGENTA_BG_BOLD="\e[1;45m"
|
||||||
|
LIB_CYAN_BG_BOLD="\e[1;46m"
|
||||||
|
LIB_LIGHTGREY_BG_BOLD="\e[1;47m"
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
## Functions
|
||||||
|
##
|
||||||
|
|
||||||
|
# Print text message
|
||||||
|
function lib_print() {
|
||||||
|
local LIB_Q=${Q:-0}
|
||||||
|
local LIB_V=${V:-0}
|
||||||
|
if [[ "$1" =~ ^\! ]]; then
|
||||||
|
printf "$LIB_RED_BG_BOLD%b$LIB_CLEAR\n" "${1#\!}"
|
||||||
|
elif [[ "$1" =~ ^\? ]]; then
|
||||||
|
if [ $LIB_V -eq 1 ] && [ $LIB_Q -ne 1 ]; then
|
||||||
|
printf "$LIB_LIGHTGREY%b$LIB_CLEAR\n" "${1#\?}"
|
||||||
|
fi
|
||||||
|
elif [[ $LIB_Q -ne 1 ]]; then
|
||||||
|
printf "%b\n" "$1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print script information
|
||||||
|
# including the last 5 changelog entries
|
||||||
|
function lib_print_info() {
|
||||||
|
printf "%12s %b\n%12s %s\n%12s %s\n%12s %s\n%12s %s\n%12s %s\n\n%12s %s\n" \
|
||||||
|
"Name:" "$LIB_BOLD$NAME$LIB_CLEAR" "Version:" "$VERSION" \
|
||||||
|
"Author:" "$AUTHOR" "License:" "$LICENSE" "Web:" "$WEBSITE" \
|
||||||
|
"Description:" "$DESCRIPTION" "Changelog:" "${CHANGELOG[0]}"
|
||||||
|
for i in "${CHANGELOG[@]:1:4}"; do
|
||||||
|
printf "%12s %s\n" "" "$i"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print version information
|
||||||
|
function lib_print_version() {
|
||||||
|
printf "%s\n" "$VERSION"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check for privileges
|
||||||
|
# Returns 0 if the current user is root and 1 if not
|
||||||
|
function lib_amiroot() {
|
||||||
|
if [[ $(whoami) != "root" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check for command availability
|
||||||
|
# Takes one or a list of space seperated commands. Returns a list of missing commands.
|
||||||
|
function lib_missing_commands() {
|
||||||
|
local MISSING_COMMANDS=""
|
||||||
|
for COMMAND in $@; do
|
||||||
|
if ! $(command -v $COMMAND &>/dev/null); then
|
||||||
|
MISSING_COMMANDS="$MISSING_COMMANDS $COMMAND"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "${MISSING_COMMANDS# }"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate a random alphanumeric string
|
||||||
|
# Optional: Supply length as intager. Default is 16.
|
||||||
|
function lib_gen_string() {
|
||||||
|
LC_ALL=C tr -dc 'a-zA-Z0-9' < /dev/urandom | head -c ${1:-16}; echo
|
||||||
|
}
|
|
@ -0,0 +1,227 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
|
||||||
|
## ## ## ## ## ## ## ## ## ## ## ## ## ##
|
||||||
|
## ##
|
||||||
|
## restic-backup.sh ##
|
||||||
|
## ##
|
||||||
|
## Simple script to help setup and run ##
|
||||||
|
## periodic Restic backup jobs ##
|
||||||
|
## ##
|
||||||
|
## ## ## ## ## ## ## ## ## ## ## ## ## ##
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
## Information
|
||||||
|
##
|
||||||
|
|
||||||
|
NAME="restic-backup.sh"
|
||||||
|
VERSION="0.2.0"
|
||||||
|
AUTHOR="david@socialnerds.org"
|
||||||
|
LICENSE="MIT"
|
||||||
|
DESCRIPTION="A simple script to help setup and run periodic Restic backup jobs."
|
||||||
|
WEBSITE="https://git.socialnerds.org/david/scripts"
|
||||||
|
CHANGELOG=("[2023-10-26][v0.2.0] Complete rewrite"
|
||||||
|
"[2022-01-01][v0.1.0] Initial version")
|
||||||
|
|
||||||
|
##
|
||||||
|
## Configuration
|
||||||
|
##
|
||||||
|
|
||||||
|
EXECUTABLE="$(basename $0)"
|
||||||
|
LIBRARIES="lib.sh"
|
||||||
|
DEPENDENCIES="basename dirname readlink tr head chmod curl restic"
|
||||||
|
REQUIRE_ROOT=0
|
||||||
|
|
||||||
|
# Files
|
||||||
|
PASSWORD="$HOME/.restic-password"
|
||||||
|
REPOSITORY="$HOME/.restic-repository"
|
||||||
|
HEALTHCHECKS="$HOME/.restic-healthchecks"
|
||||||
|
|
||||||
|
# Build the Restic command
|
||||||
|
RESTIC_BINARY="$(command -v restic)"
|
||||||
|
RESTIC_OPTIONS="-q"
|
||||||
|
RESTIC_COMMAND="$RESTIC_BINARY --password-file $PASSWORD --repository-file $REPOSITORY $RESTIC_OPTIONS"
|
||||||
|
|
||||||
|
# How many snapshots should be kept?
|
||||||
|
SNAPSHOTS=32
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
## Functions
|
||||||
|
##
|
||||||
|
|
||||||
|
# Print help information
|
||||||
|
function print_help() {
|
||||||
|
printf "%s\n\n%s\n%b\n\n%s\n %-15s %s\n %-15s %s\n %-15s %s\n %-15s %s\n %-15s %s\n" \
|
||||||
|
"$DESCRIPTION" "Usage:" "$LIB_BOLD$EXECUTABLE <options> <path or Restic keyword>$LIB_CLEAR" "Options:" \
|
||||||
|
"-c, --checks" "Enable Healthchecks" \
|
||||||
|
"-h, --help" "Print help screen and exit" \
|
||||||
|
"-i, --info" "Print script information and exit" \
|
||||||
|
"-v, --verbose" "More verbose output" \
|
||||||
|
"-q, --quiet" "No output except errors (overrides -v)"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
## Preflight
|
||||||
|
##
|
||||||
|
|
||||||
|
# Load BASH libraries
|
||||||
|
SCRIPT_PATH=$(readlink -f "$0")
|
||||||
|
SCRIPT_DIR=$(dirname "$SCRIPT_PATH")
|
||||||
|
for LIBRARY in $LIBRARIES; do
|
||||||
|
if [[ -r "$SCRIPT_DIR/$LIBRARY" ]]; then
|
||||||
|
#echo "Loading library file [$SCRIPT_DIR/$LIBRARY]"
|
||||||
|
source "$SCRIPT_DIR/$LIBRARY"
|
||||||
|
else
|
||||||
|
echo "Error: Cannot load library file [$SCRIPT_DIR/$LIBRARY]"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check for root privileges
|
||||||
|
if ! lib_amiroot && [[ $REQUIRE_ROOT -eq 1 ]]; then
|
||||||
|
lib_print "!You need to have root privileges"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for dependencies
|
||||||
|
MISSING_COMMANDS=$(lib_missing_commands $DEPENDENCIES)
|
||||||
|
if [ -n "$MISSING_COMMANDS" ]; then
|
||||||
|
lib_print "!One or more commands missing [$MISSING_COMMANDS]"
|
||||||
|
lib_print "Try installing them with your package manager"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
## Liftoff
|
||||||
|
##
|
||||||
|
|
||||||
|
while [[ "$1" =~ ^- && ! "$1" == "--" ]]; do
|
||||||
|
case $1 in
|
||||||
|
-c|--checks)
|
||||||
|
C=1
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
H=1
|
||||||
|
;;
|
||||||
|
-i|--info)
|
||||||
|
I=1
|
||||||
|
;;
|
||||||
|
-v|--verbose)
|
||||||
|
V=1
|
||||||
|
;;
|
||||||
|
-q|--quiet)
|
||||||
|
Q=1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
lib_print "!Unknown option [$1]"
|
||||||
|
lib_print "Try --help or -h for available options"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "$1" == '--' ]]; then
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $I -eq 1 ]]; then
|
||||||
|
lib_print_info
|
||||||
|
exit 0
|
||||||
|
elif [[ $H -eq 1 ]]; then
|
||||||
|
print_help
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$1" ]]; then
|
||||||
|
print_help
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
# Generate a new password file if it is missing or empty
|
||||||
|
if [[ ! -s $PASSWORD ]]; then
|
||||||
|
lib_gen_string 32 > $PASSWORD
|
||||||
|
chmod 600 $PASSWORD
|
||||||
|
lib_print "New password file generated since it did not exist or was empty [$PASSWORD]"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate a new repo file if it is missing or empty
|
||||||
|
if [[ ! -s $REPOSITORY ]]; then
|
||||||
|
echo -n "Repository URL: "; read -r INPUT
|
||||||
|
echo $INPUT > $REPOSITORY
|
||||||
|
chmod 600 $REPOSITORY
|
||||||
|
lib_print "New repository file generated since it did not exist or was empty [$REPOSITORY]"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate a new healthchecks file if it is missing or empty
|
||||||
|
if [[ ! -s $HEALTHCHECKS ]] && [[ $C -eq 1 ]]; then
|
||||||
|
echo -n "Healthchecks URL: "; read -r INPUT
|
||||||
|
if [[ -n "$INPUT" ]]; then
|
||||||
|
echo "$INPUT" > $HEALTHCHECKS
|
||||||
|
chmod 600 $HEALTHCHECKS
|
||||||
|
lib_print "New healthchecks file generated [$HEALTHCHECKS]"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Initialize a new repo if the URL has no config file
|
||||||
|
if ! $($RESTIC_COMMAND snapshots >/dev/null 2>&1); then
|
||||||
|
if ! $($RESTIC_COMMAND init >/dev/null 2>&1); then
|
||||||
|
lib_print "!A problem occured while initializing a new repository"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
lib_print "New repository initialized"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run the Restic repository check
|
||||||
|
if ! $($RESTIC_COMMAND check >/dev/null 2>&1); then
|
||||||
|
lib_print "!Repository check failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$1" =~ ^/ && -r "$1" ]]; then
|
||||||
|
# Signal Healthchecks start if enabled
|
||||||
|
if [[ "$C" -eq 1 ]]; then
|
||||||
|
HEALTHCHECKS_URL=$(cat $HEALTHCHECKS)
|
||||||
|
curl -fsS -m 10 --retry 5 -o /dev/null $HEALTHCHECKS_URL/start
|
||||||
|
fi
|
||||||
|
# Run the actual backup
|
||||||
|
if ! $($RESTIC_COMMAND backup --one-file-system ${@:2} "$1" >/dev/null 2>&1); then
|
||||||
|
lib_print "!Something went wrong while running backup [$1]"
|
||||||
|
# Signal Healthchecks fail if enabled
|
||||||
|
if [[ "$C" -eq 1 ]]; then
|
||||||
|
curl -fsS -m 10 --retry 5 -o /dev/null $HEALTHCHECKS_URL/fail >/dev/null 2>&1
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# Delete old snapshots
|
||||||
|
if ! $($RESTIC_COMMAND forget --keep-last $SNAPSHOTS --path "$1" --prune >/dev/null 2>&1); then
|
||||||
|
lib_print "!Something went wrong while deleting old snapshots [$1]"
|
||||||
|
# Signal Healthchecks fail if enabled
|
||||||
|
if [[ "$C" -eq 1 ]]; then
|
||||||
|
curl -fsS -m 10 --retry 5 -o /dev/null $HEALTHCHECKS_URL/fail >/dev/null 2>&1
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# Signal Healthchecks success if enabled
|
||||||
|
if [[ "$C" -eq 1 ]]; then
|
||||||
|
curl -fsS -m 10 --retry 5 -o /dev/null $HEALTHCHECKS_URL >/dev/null 2>&1
|
||||||
|
fi
|
||||||
|
elif [[ "$1" =~ ^(backup|cache|cat|check|copy|diff|dump|find|forget|generate|help|init|key|list|ls|migrate|mount|prune|recover|repair|restore|rewrite|snapshots|stats|tag|unlock|version)$ ]]; then
|
||||||
|
# Wrapper mode
|
||||||
|
$RESTIC_COMMAND $@
|
||||||
|
else
|
||||||
|
lib_print "!The given path must be absolute and readable [$1]"
|
||||||
|
lib_print "Or you can try a Restic keyword directly for wrapper mode"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
## Here be dragons
|
||||||
|
##
|
||||||
|
|
||||||
|
exit 0
|
Loading…
Reference in New Issue