Skip to content

Instantly share code, notes, and snippets.

@DennisLfromGA
Last active September 5, 2021 15:45
Show Gist options
  • Save DennisLfromGA/36629fd1a28a451658401b01609bd939 to your computer and use it in GitHub Desktop.
Save DennisLfromGA/36629fd1a28a451658401b01609bd939 to your computer and use it in GitHub Desktop.
A script to restore brioche containers from brioche backups
#!/bin/bash
# brio-restore - A script to list brioche backups & restore brioche containers
##
#######################
### Setup variables ###
#######################
##
APPL="${0##*/}"
CONTAINERS=''
DELAY=5
DOWNLOADS="${DOWNLOADS:-${HOME}/Downloads}"
RESTORALS=''
USAGE="
====================================================================
= PLEASE NOTE: This script is deprecated and replaced by 'brio-br' =
====================================================================
## brio-restore - A script to list brioche backups & restore containers
USAGE: ${APPL} restores brioche container backups found under '${DOWNLOADS}'
(default: ${HOME}/Downloads) to the named container under '~/brioche/'.
The script will prompt for each container before proceeding.
NOTE: Will append the last modified date & time to any existing container folders found.
Optionally displays the script version, version history & help/usage (this blurb).
Options:
-c Check for & list backup files found in ${DOWNLOADS}
-h Displays this help/usage message and exits
-v Displays the current version of '${APPL}' and exits
-V Displays version number plus version history & exits
====================================================================
= Please install 'brio-br' using 'install.brio-br' =
====================================================================
"
# VERSION format: "n.n.$(date +%Y%m%d%H%M)"
VERSION='3.1.202109051056'
VERHIST="\
${APPL}-3.1.202109051056 : This script is deprecated and replaced by 'brio-br'
${APPL}-3.0.202109011756 : Renamed script from brioche-restore to brio-restore
${APPL}-3.0.202109011756 + and backup file from brioche-... to end with .brio
${APPL}-2.4.202109011719 : Add command-line options [-v,-V,-h]
${APPL}-2.3.202109011647 : Use 'pv' when installed instead of 'spinner'
${APPL}-2.2.202108311120 : Added backup file selection
${APPL}-2.1.202108271957 : Cleaned up several routines
${APPL}-2.0.202108231443 : Converted conditionals, etc. to functions
${APPL}-1.1.202108221629 : Added version and version history
${APPL}-1.0.202108201513 : Created $APPL with 1 revision."
## Planned revisons:
# ${APPL}-4.0. : Combined both brio-backup & brio-restore to brio-br
##
#######################
### Setup functions ###
#######################
##
### functions with b/r prefix are for backup/restore respectively
### Following two functions, error & spinner, borrowed from the 'crouton' authors
##
## exit with exit code $1, spitting out message $@ to stderr
echo_e='/bin/echo -e'
error() {
local ecode="${1}"
shift
${echo_e} "${*}" 1>&2
exit "${ecode}"
}
##
## Prints out a fancy spinner that updates every time a line is fed in, unless
## the output is not to a tty, in which case it just prints a new line.
# $1: number of lines between each update of the spinner
# $2...: Command to be run
# Erases the line each time, so it will always be at position 0.
# Either expect this and put text later in the line, or give this its own line.
spinner() {
local spin="$1"
shift
if [ -t 2 ]; then
# Keep track of the exit status of the piped command
local ret="`(("$@" || echo "$?" 1>&3) | mawk -Winteractive '
BEGIN {
printf "\r"
}
{
y = (y+1) % '"$spin"'
if (y == 0) {
x = (x+1) % 4
printf substr("\|/-", x+1, 1) "\r"
}
}' 1>&2) 3>&1`"
if [ -n "$ret" ]; then
return "$ret"
fi
else
echo 1>&2
"$@" 1>/dev/null
fi
}
##
check_for_opts() {
## Get command line parameters
local OPTIND
while getopts chvV OPT; do
case ${OPT} in
c) r_check_for_backups
echo; error 0 "${USAGE}";;
h) error 0 "$USAGE";;
v) echo "$VERHIST" | grep $VERSION 1>&2; exit 0;;
V) error 0 "VERSION:${VERSION}\n${VERHIST}" ;;
\?) error 2 "$USAGE";;
esac
done
shift "$((OPTIND-1))"
}
##
r_check_for_downloads() {
if [ ! -d ${DOWNLOADS} ]; then
echo "Sorry, no '${DOWNLOADS}' directory exists."
echo "If your backups are somewhere else please either move them under ${DOWNLOADS}"
error 1 "or invoke this script with 'DOWNLOADS=[path-to-backups-folder] ${APPL}'".
fi
}
##
r_check_for_backups() {
local CONT REST
cd ${DOWNLOADS}
for REST in $(ls *.brio 2>/dev/null); do
CONT=$(echo ${REST} | cut -d '.' -f1)
CONTAINERS="${CONTAINERS} ${CONT},"
done
CONTAINERS="$(echo "${CONTAINERS}" | tr ',' '\n' | sort -u | tr '\n' ',')"
if [ -n "${CONTAINERS}" ]; then
CONTAINERS="$(echo ${CONTAINERS}|sed 's/^,//; s/,$//')"
echo "Backups found for brioche container(s)${CONTAINERS} - see below:"
echo "(if multiple backups are found for the same container then you can select one from a list.)"
echo
ls -ltr *.brio 2>/dev/null
else
echo "No brioche container backups found ..."
error 1 "Note: They should be named: '[CONTAINER_NAME].[DATE-TIME].brio"
fi
}
##
r_check_for_containers() {
local CONT EXIST
if [ ! -d ${HOME}/brioche ]; then
echo "No '~/brioche/' directory exists, making one now ..."
mkdir -p ${HOME}/brioche
else
echo
echo "Found '~/brioche/' directory ..."
fi
sudo chown chronos:root ${HOME}/brioche
cd ${HOME}/brioche/
CONTAINERS="$(echo ${CONTAINERS}|sed 's/,/ /')"
for CONT in ${CONTAINERS}; do
if [ -d "${CONT}" ]; then
EXIST="${EXIST}, ${CONT}"
fi
done
EXIST="$(echo ${EXIST}|sed 's/^,//; s/,$//')"
echo
echo "These corresponding brioche containers exist and if selected for restoral will be"
echo "be renamed to have their last modified date & time appended to them: ${EXIST}"
}
##
r_ask_for_restoral() {
local BEGIN CONT NMBR RESP REST
cd ${DOWNLOADS}
for CONT in ${CONTAINERS}; do
NMBR="$(ls -1 ${CONT}*.brio 2>/dev/null|wc -l)"
if [ "${NMBR}" -gt 1 ]; then
echo
echo "There were ${NMBR} backups found for '${CONT}'."
echo "Restore one of the '${CONT}' brioche backups to ~/brioche/${CONT} [Ysra] ?"
else
REST="$(ls -tr ${CONT}*.brio 2>/dev/null)"
echo
echo "Restore brioche backup '${REST}' to ~/brioche/${CONT} [Ysra] ?"
fi
read -n 1 -p "PRESS 'y' to restore, 's' to SKIP, 'r' to RESTART or 'a' to ABORT/QUIT! " RESP
if [ -n "${RESP}" ]; then
case ${RESP} in
[yY])
echo; echo "Got '${RESP}', '${CONT}' added to restorals ..."
RESTORALS="${RESTORALS} ${CONT},"
;;
[sS]|[nN])
echo; echo "Got '${RESP}', so Skipping '${CONT}' ..."
continue
;;
[rR])
echo; echo "Got '${RESP}', so Restarting ..."
CONT=''; NMBR=''; RESP=''; REST=''; RESTORALS=''
r_ask_for_restoral
;;
[aA]|[xX])
echo; echo -n "Got '${RESP}, '"
error 0 "okay, ABORTING/QUITTING ..."
;;
*)
echo; echo "Got '${RESP}', no such option '${RESP}' ..."
echo "Only 'y' to restore, 's' to SKIP, 'r' to RESTART or 'a' to ABORT/QUIT are accepted."
error 1 "${USAGE}"
;;
esac
else
echo; echo "Got 'ENTER', '${CONT}' added to restorals ..."
RESTORALS="${RESTORALS} ${CONT},"
fi
done
RESTORALS="$(echo ${RESTORALS}|sed 's/^ //; s/,$//g')"
echo
echo -n "Ready to restore container(s) '${RESTORALS}' - press 'ENTER' to begin or 'Ctrl-C' to ABORT/QUIT: "
read BEGIN
}
##
r_do_restoral() {
local CONT DIRDATE FILES NMBR PS3 REST
RESTORALS="$(echo ${RESTORALS}|sed 's/,//g')"
cd ${DOWNLOADS}
for CONT in ${RESTORALS}; do
NMBR="$(ls -1 ${CONT}*.brio 2>/dev/null|wc -l)"
if [ "${NMBR}" -gt 1 ]; then
echo
echo "More than one backup for '${CONT}' exists, please select one from the list below:"
echo "(the backup files are listed in chronogical order, #1 will be the most recent.)"
FILES="$(ls -1Ar ${CONT}*.brio)"
PS3="Choose one of the above backup files to restore to the '${CONT}' container,"$'\n'"or select Skip, Restart, or Abort/Quit ? "
echo
select REST in ${FILES} Skip Restart Abort/Quit; do
if [ -z "$REST" ] ; then
echo "[ERROR] Invalid option"
continue
fi
case "$REST" in
Skip)
echo; echo "Got '${REST}', so Skipping '${CONT}' ..."
continue 2
;;
Restart)
echo; echo "Got '${REST}', so Restarting ..."
CONT=''; FILES=''; NMBR=''; PS3=''; REST=''; RESTORALS=''
r_ask_for_restoral
;;
Abort/Quit)
echo; echo -n "Got '${REST}, '"
error 0 "okay, Aborting/Quitting ..."
;;
*) echo "Brunch backup file selected: $REST"
RESTORALS="${RESTORALS} ${CONT},"
break
;;
esac
done
echo
else
REST="$(ls -tr ${CONT}*.brio 2>/dev/null)"
fi
if [ ! -d ${HOME}/brioche/${CONT} ]; then
echo
echo "No '~/brioche/${CONT}' directory exists, making one now ..."
else
echo
DIRDATE="$(date -r ${HOME}/brioche/${CONT} '+%Y%m%d%H%M')"
echo "WARNING: A brioche container '${CONT}' already exists, it is being renamed: ${CONT}.${DIRDATE} ..."
mv -n ${HOME}/brioche/${CONT} ${HOME}/brioche/${CONT}.${DIRDATE}
echo "Stopping '${CONT}' - just in case ..."
brioche ${CONT}.${DIRDATE} stop 2>/dev/null
sleep ${DELAY}
fi
mkdir -p ${HOME}/brioche/${CONT}
sudo chown chronos:root ${HOME}/brioche/${CONT}
echo "Restoring '${REST}' to '~/brioche/${CONT}' ..."
trap "sudo rm -f '${HOME}/brioche/${CONT}; \
mv -f ${HOME}/brioche/${CONT}.${DIRDATE} ${HOME}/brioche/${CONT} 2>/dev/null \
error 2 \"Restoral up of '${CONT}' aborted, container deleted!\"" INT HUP TERM 0
if type -P pv 1>/dev/null; then
# "'pv' is installed."
sudo pv -Ws $(du -s ${REST} | awk '{print $1}') ${REST} | \
tar -zx -C . || FAILED="${FAILED} ${CONT}"
if echo ${FAILED} | grep -q ${CONT}; then
mv -f ${HOME}/brioche/${CONT}.${DIRDATE} ${HOME}/brioche/${CONT} 2>/dev/null
echo "Restoral of '${CONT}' failed!"
else
RESTORED="${RESTORED} ${CONT},"
fi
else
# "'pv' is NOT installed."
spinner 10 sudo tar --checkpoint=10 --checkpoint-action=exec=echo --numeric-owner \
-xzf ${REST} -C ${HOME}/brioche/${CONT} 1>&2 || FAILED="${FAILED} ${CONT}"
if echo ${FAILED} | grep -q ${CONT}; then
mv -f ${HOME}/brioche/${CONT}.${DIRDATE} ${HOME}/brioche/${CONT} 2>/dev/null
echo "Restoral of '${CONT}' failed!"
else
RESTORED="${RESTORED} ${CONT},"
fi
fi
trap - INT HUP TERM 0
RESTORED="$(echo ${RESTORED}|sed 's/^ //')"
FAILED="$(echo ${FAILED}|sed 's/^ //')"
echo "Restoral of '${CONT}' finished ..."
sudo chown chronos:root ${HOME}/brioche/${CONT}
done
}
##
r_report_results() {
echo
if [ -n "${FAILED}" ]; then
echo "Restoral FAILED for brioche container(s) ${FAILED} !"
fi
if [ -n "${RESTORED}" ]; then
RESTORED="$(echo ${RESTORED}|sed 's/,$//')"
echo "Retorals complete for brioche container(s) ${RESTORED}"
echo
ls -l ${HOME}/brioche/
else
echo "No brioche container restored ..."
fi
}
##
####################
### Main section ###
####################
##
check_for_opts "$@"
error 0 "${USAGE}"
##
if [ ${UID:-$(id -u)} -eq 0 ]; then
echo
echo "ERROR: ${APPL} must NOT be run as root!"
error 1 "${USAGE}"
fi
r_check_for_downloads
r_check_for_backups
r_check_for_containers
r_ask_for_restoral
r_do_restoral
r_report_results
echo
exit 0
@DennisLfromGA
Copy link
Author

Inadvertently replaced brioche-restore with brioche-backup, this revision reverts that change.

@DennisLfromGA
Copy link
Author

PLEASE NOTE: This script is deprecated and replaced by 'brio-br'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment