Compare commits

..

3 Commits

Author SHA1 Message Date
Andrew Hurley a267a6929d day of week 2022-12-13 20:02:00 +11:00
Andrew Hurley 669f138f9f typo 2022-11-01 18:02:19 +11:00
Andrew Hurley bbd3a00378 add copy backup to another drive 2022-11-01 18:00:23 +11:00
6 changed files with 69 additions and 142 deletions

1
b2v.sh
View File

@ -5,7 +5,6 @@
PREFIX="" PREFIX=""
if [[ -v 1 ]]; then if [[ -v 1 ]]; then
PREFIX="${1}_" PREFIX="${1}_"
printf "Add prefix $PREFIX\n"
fi fi
cprompt () { cprompt () {

View File

@ -1 +1 @@
14 4 * * * root /srv/backup/backup.sh -r "/srv/fsback" docker 2>&1 |tee /srv/fsback/$(date +%^a).log 14 4 * * * root /srv/backup/backup.sh 2>&1 |tee /var/log/docker-backup.log

View File

@ -1,50 +1,10 @@
#!/bin/bash #!/bin/bash
usage () { pushd /srv/backup && \
printf "Usage: backup.sh <options> <project> [<project>]\n" printf "Backup start: $(date)\n" && \
printf " project = Compose project folder(s).\n" ./vvv.sh docker && \
printf " Option r <location>: rsync to another location - will make path (rsync mkpath option used)\n" nice ./v2b.sh -u backup_docker && \
} rsync -av --mkpath ./_vols_/ "/mnt/9a986e29-6705-472a-a66a-b7ca3da819bd/dockerbackups/$(date +%^a)/" && \
pexit () {
printf "${1}\n"
exit 1
}
RSYNC=""
while getopts ':r:' OPT; do
case $OPT in
r) RSYNC="${OPTARG}";;
\?) usage; exit;;
esac
done
shift $((OPTIND -1))
if [[ $# -lt 1 ]]; then
pexit "Error: missing project(s)"
fi
if [[ -n $RSYNC ]]; then
HN=$(hostname -f)
if [[ ! $HN =~ "." ]]; then
pexit "Error: fully quaififed hostname required (add to /etc/hosts - 127.0.0.11)"
fi
printf "Hostname: ${HN}\n"
fi
pushd /srv/backup || pexit "Error: changing to backup directory"
printf "Backup start: $(date)\n"
for PROJECT in $@; do
./vvv.sh "${PROJECT}" || pexit "Error: using vvv.sh ${PROJECT}"
done
nice ./v2b.sh -u backup || pexit "Error: using v2b.sh -u backup"
if [[ -n $RSYNC ]]; then
RSYNC="${RSYNC}/${HN}/$(date +%^a)"
rsync -av --mkpath ./_vols_/ "${RSYNC}/" || pexit "Error: using rsync -av --mkpath ./_vols_/ ${RSYNC}/"
fi
printf "Backup end: $(date)\n" && \ printf "Backup end: $(date)\n" && \
popd || pexit "Error: using popd" popd
# e.g. rsync -av --mkpath ./_vols_/ "/srv/fsback/${HN}/$(date +%^a)/"

43
v2b.sh
View File

@ -4,29 +4,25 @@
set -u set -u
set -o pipefail set -o pipefail
if [[ $(id -u) -ne "0" ]]; then
printf "Elevated privileges required\n"
exit 1
fi
UMASK="$(umask)" UMASK="$(umask)"
cprompt () { cprompt () {
if [[ $UNATTENDED == "true" ]]; then if [[ $UNATTENDED == "true" ]]; then
return; return;
fi fi
read -r -s -N 1 -p "Press 'Enter' to backup, 'Escape' to skip..." read -r -s -N 1 -p "Press 'Enter' to continue "
if [[ $REPLY != $'\n' ]]; then if [[ $REPLY != $'\n' ]]; then
printf "backup skipped!\n" printf "\n"
printf " Backup stopped!\n"
return 1 return 1
else else
printf "backup starting.\n" printf "\n"
fi fi
} }
usage () { usage () {
printf "v2b.sh <option> [ <prefix> ]\n" printf "v2b.sh <option> [ <prefix> ]\n"
printf " <prefix> only backup volumes with this prefix (underscore not required)\n" printf " <prefix> only backup volumes with this prefix\n"
printf " option: k (keep existing backups)\n" printf " option: k (keep existing backups)\n"
printf " option: p (remove prefix from tar archive file name\n" printf " option: p (remove prefix from tar archive file name\n"
printf " option: u (unattended backup)\n" printf " option: u (unattended backup)\n"
@ -44,7 +40,7 @@ while getopts ':s:pku' OPT; do
case $OPT in case $OPT in
s) SEND="true"; ADDR="${OPTARG}"; OUTPUT="${OUTPUT} Option: SEND BACKUPS\n";; s) SEND="true"; ADDR="${OPTARG}"; OUTPUT="${OUTPUT} Option: SEND BACKUPS\n";;
p) REMOVE="true"; OUTPUT="${OUTPUT} Option: PREFIXES REMOVED\n";; p) REMOVE="true"; OUTPUT="${OUTPUT} Option: PREFIXES REMOVED\n";;
k) KEEP="true"; OUTPUT="${OUTPUT} Option: KEEP EXISTING BACKUPS\n";; r) KEEP="true"; OUTPUT="${OUTPUT} Option: KEEP EXISTING BACKUPS\n";;
u) UNATTENDED="true"; OUTPUT="${OUTPUT} Option: UNATTENDED BACKUP\n";; u) UNATTENDED="true"; OUTPUT="${OUTPUT} Option: UNATTENDED BACKUP\n";;
\?) usage; exit;; \?) usage; exit;;
esac esac
@ -54,9 +50,9 @@ shift $((OPTIND -1))
FOLDER="_vols_" FOLDER="_vols_"
if [[ $# > 0 ]]; then if [[ $# > 0 ]]; then
VOLUMES="$(docker volume ls -q |grep "${1}_")" VOLUMES="$(sudo docker volume ls -q |grep "${1}")"
else else
VOLUMES="$(docker volume ls -q)" VOLUMES="$(sudo docker volume ls -q)"
fi fi
if [[ -z $VOLUMES ]]; then if [[ -z $VOLUMES ]]; then
@ -70,14 +66,13 @@ else
LASTF="${FOLDER}" LASTF="${FOLDER}"
fi fi
USER="$(stat -c '%u' $BASH_SOURCE)"
INDEX="$((( ${LASTF#${FOLDER}} + 0 )))" INDEX="$((( ${LASTF#${FOLDER}} + 0 )))"
NEWFL="${FOLDER}$(printf "%05d" $((( ${INDEX} + 1 ))))" NEWFL="${FOLDER}$(printf "%05d" $((( ${INDEX} + 1 ))))"
TEMPF="$(sudo -u \#${USER?err} mktemp -dt -p $PWD _XXXXXXXXXXXXXXX_)" TEMPF="$(mktemp -dt -p $PWD _XXXXXXXXXXXXXXX_)"
for VOL in ${VOLUMES}; do for VOL in ${VOLUMES}; do
if [[ $REMOVE == "true" ]]; then if [[ $REMOVE == "true" ]]; then
if [[ $# > 0 ]]; then if [[ -v 1 ]]; then
TAR="${VOL#${1}_}.tar.bz2" TAR="${VOL#${1}_}.tar.bz2"
else else
TAR="${VOL#*_}.tar.bz2" TAR="${VOL#*_}.tar.bz2"
@ -85,15 +80,13 @@ for VOL in ${VOLUMES}; do
else else
TAR="${VOL}.tar.bz2" TAR="${VOL}.tar.bz2"
fi fi
printf "\n${VOL} --> ${TEMPF}/${TAR}\n" printf "${VOL} --> ${TEMPF}/${TAR}\n"
cprompt || continue cprompt || break
docker run --rm --log-driver none \ sudo docker run --rm --log-driver none \
-v "${VOL}:/volume" \ -v "${VOL}:/volume" \
-v "${TEMPF}:/backup" \ -v "${TEMPF}:/backup" \
loomchild/volume-backup backup -v "${TAR}" loomchild/volume-backup backup -v "${TAR}"
if [[ -f "${TEMPF}/${TAR}" ]]; then sudo chmod 600 "${TEMPF}/${TAR}"
chmod 600 "${TEMPF}/${TAR}"
fi
done done
if [[ -z "$(ls -A ${TEMPF})" ]]; then if [[ -z "$(ls -A ${TEMPF})" ]]; then
@ -107,12 +100,12 @@ else
if mv "${TEMPF}" "${FOLDER}"; then if mv "${TEMPF}" "${FOLDER}"; then
if [[ $SEND == "true" ]]; then if [[ $SEND == "true" ]]; then
if [[ $ADDR =~ ":" ]]; then if [[ $ADDR =~ ":" ]]; then
if ssh "${ADDR%:*}" "mkdir -p ${ADDR#*:}"; then if sudo ssh "${ADDR%:*}" "mkdir -p ${ADDR#*:}"; then
scp "${FOLDER}"/* "${ADDR}" sudo scp "${FOLDER}"/* "${ADDR}"
fi fi
else else
if ssh "${ADDR}" "mkdir -p ${PWD}/_$(hostname -f)_"; then if sudo ssh "${ADDR}" "mkdir -p ${PWD}/_$(hostname -f)_"; then
scp "${FOLDER}"/* "${ADDR}:${PWD}/_$(hostname -f)_" sudo scp "${FOLDER}"/* "${ADDR}:${PWD}/_$(hostname -f)_"
fi fi
fi fi
fi fi

85
vvv.sh
View File

@ -4,13 +4,8 @@
set -u set -u
set -o pipefail set -o pipefail
if [[ $(id -u) -ne "0" ]]; then
printf "Elevated privileges required\n"
exit 1
fi
usage () { usage () {
printf "Usage: vvv.sh <options> <project>\n" printf "Usage: vvv.sh <project>\n"
printf " project = Compose project folder.\n" printf " project = Compose project folder.\n"
printf " Option r: restore operation\n" printf " Option r: restore operation\n"
printf " Option d: keep containers down - don't bring back up\n" printf " Option d: keep containers down - don't bring back up\n"
@ -18,21 +13,26 @@ usage () {
RESTORE="false" RESTORE="false"
DOWN="false" DOWN="false"
OUTPUT=" Option: BACKUP OPERATION" OUTPUT=""
while getopts ':rd' OPT; do while getopts ':rd' OPT; do
case $OPT in case $OPT in
r) RESTORE="true"; OUTPUT=" Option: RESTORE OPERATION";; r) RESTORE="true"; OUTPUT="${OUTPUT} Option: RESTORE OPERATION";;
d) DOWN="true"; OUTPUT="${OUTPUT} Option: KEEP DOWN";; d) DOWN="true"; OUTPUT="${OUTPUT} Option: KEEP DOWN";;
\?) usage; exit;; \?) usage; exit;;
esac esac
done done
shift $((OPTIND -1)) shift $((OPTIND -1))
if [[ $RESTORE == "true" ]] && [[ ! -f docker-restore.sh ]]; then
echo "Problem: docker-restore.sh missing!"
exit 1
fi
scripts () { scripts () {
for MODE in backup restore; do for MODE in backup restore; do
FILE="docker-${MODE}.sh" FILE="docker-${MODE}.sh"
SCRIPT="#!/bin/bash"$'\n' SCRIPT="#!/bin/bash"$'\n'
SCRIPT="${SCRIPT}docker run --rm \\"$'\n' SCRIPT="${SCRIPT}sudo docker run --rm \\"$'\n'
SCRIPT="${SCRIPT} --name volumerize \\"$'\n' SCRIPT="${SCRIPT} --name volumerize \\"$'\n'
SCRIPT="${SCRIPT} -e TZ=Australia/Perth \\"$'\n' SCRIPT="${SCRIPT} -e TZ=Australia/Perth \\"$'\n'
SCRIPT="${SCRIPT} -e VOLUMERIZE_SOURCE=/source \\"$'\n' SCRIPT="${SCRIPT} -e VOLUMERIZE_SOURCE=/source \\"$'\n'
@ -54,11 +54,12 @@ scripts () {
printf "Fatal error 1.\n" printf "Fatal error 1.\n"
exit 1 exit 1
fi fi
printf "${SCRIPT}" |sudo -u "#${USER?err}" tee "${FILE}" printf "${SCRIPT}" > "${FILE}"
chmod +x "${FILE}"
done done
} }
if [[ ! $# -eq 1 ]]; then if [[ $# -lt 1 ]]; then
usage usage
exit 1 exit 1
fi fi
@ -69,78 +70,52 @@ if [[ ! -d "../${PROJECT}" ]]; then
exit 1 exit 1
fi fi
VOLUMES="$(ls /var/lib/docker/volumes |grep "${PROJECT}_")" VOLUMES="$(sudo ls /var/lib/docker/volumes |grep "${PROJECT}_")"
if [[ -z "$VOLUMES" ]]; then if [[ -z "$VOLUMES" ]]; then
printf "There are no volumes found to backup/restore!\n" printf "There are no volumes found to backup/restore!\n"
exit 1 exit 1
fi fi
printf "${OUTPUT}\n"
if timeout --preserve-status --foreground 10 bash -c 'read -r -s -N 1 -p "Starting delay of 10 seconds. Press a key to cancel... "'; then
printf "cancelled\n"
exit 1
else
printf "starting\n"
fi
USER=$(stat -c '%u' $BASH_SOURCE)
pushd "../${PROJECT}" > /dev/null || exit 1 pushd "../${PROJECT}" > /dev/null || exit 1
if [[ $RESTORE == "true" ]] && [[ ! -f docker-restore.sh ]]; then
echo "Problem: docker-restore.sh missing!"
exit 1
fi
if [[ ! $RESTORE == "true" ]]; then if [[ ! $RESTORE == "true" ]]; then
scripts scripts
fi fi
for COMP in docker-compose*.yml; do COMMAND="sudo docker compose stop"
if command -v docker-compose; then
COMMAND="docker-compose -f $COMP stop"
else
COMMAND="docker compose -f $COMP stop"
fi
printf "${COMMAND}\n" printf "${COMMAND}\n"
if ! bash -c "${COMMAND}"; then ${COMMAND}
if ! ${COMMAND}; then
printf "Services 'docker compose stop' error." printf "Services 'docker compose stop' error."
exit 1 exit 1
fi fi
done COMMAND="sudo docker compose rm -f"
for COMP in docker-compose*.yml; do
if command -v docker-compose; then
COMMAND="docker-compose -f $COMP rm -f"
else
COMMAND="docker compose -f $COMP rm -f"
fi
printf "${COMMAND}\n" printf "${COMMAND}\n"
if ! bash -c "${COMMAND}"; then ${COMMAND}
if ! ${COMMAND}; then
printf "Services 'docker compose rm' error." printf "Services 'docker compose rm' error."
exit 1 exit 1
fi fi
done
if [[ $RESTORE == "true" ]]; then if [[ $RESTORE == "true" ]]; then
bash "./docker-restore.sh" "./docker-restore.sh"
else else
bash "./docker-backup.sh" "./docker-backup.sh"
if [[ $DOWN = "false" ]]; then if [[ $DOWN = "false" ]]; then
for COMP in docker-compose*.yml; do COMMAND="sudo docker compose up -d"
if command -v docker-compose; then
COMMAND="docker-compose -f $COMP up -d"
else
COMMAND="docker compose -f $COMP up -d"
fi
printf "${COMMAND}\n" printf "${COMMAND}\n"
if ! bash -c "${COMMAND}"; then if ! ${COMMAND}; then
printf "Services 'up' error." printf "Services 'up' error."
exit 1 exit 1
fi fi
done
fi fi
fi fi
COMMAND="sudo docker compose up -d"
printf "${COMMAND}\n"
if ! ${COMMAND}; then
printf "Services 'up' error."
exit 1
fi
popd > /dev/null || exit 1 popd > /dev/null || exit 1