From 9585733cade94d25ea50cc308317fd9dca2fd3fe Mon Sep 17 00:00:00 2001 From: Dominic Ricottone Date: Wed, 14 Sep 2022 21:05:13 -0500 Subject: [PATCH] Initial commit --- Makefile | 21 +++++++++++++ backup | 41 +++++++++++++++++++++++++ backup-files | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++ backup-legal | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++ backup-music | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 316 insertions(+) create mode 100644 Makefile create mode 100755 backup create mode 100755 backup-files create mode 100755 backup-legal create mode 100755 backup-music diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6eb1d41 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +BIN_DIR?=/usr/local/bin +LIB_DIR?=/usr/local/lib +COMP_DIR?=/usr/local/etc/bash_completion.d + +.PHONY: install uninstall test + +install: + install -m755 backup $(BIN_DIR)/backup + install -m755 backup-files $(BIN_DIR)/backup-files + install -m755 backup-legal $(BIN_DIR)/backup-legal + install -m755 backup-music $(BIN_DIR)/backup-music + +uninstall: + rm $(BIN_DIR)/backup + rm $(BIN_DIR)/backup-files + rm $(BIN_DIR)/backup-legal + rm $(BIN_DIR)/backup-music + +test: + #shellcheck *.bash *.sh $(LIB_DIR)/mylib.bash $(LIB_DIR)/myparse.bash $(LIB_DIR)/myminiparse.sh + diff --git a/backup b/backup new file mode 100755 index 0000000..22eafd8 --- /dev/null +++ b/backup @@ -0,0 +1,41 @@ +#!/bin/sh + +if [ $# -eq 0 ]; then + /usr/bin/printf "USAGE: backup COMMAND\n" + exit 1 +fi + +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help|help) + /usr/bin/printf "backup COMMAND\n" + /usr/bin/printf "Commands:\n" + /usr/bin/printf " help show help text\n" + /usr/bin/printf " files backup local files\n" + /usr/bin/printf " legal backup a legal documents directory\n" + /usr/bin/printf " music backup a music media directory\n" + exit 0 + ;; + + files) + shift + exec /usr/local/bin/backup-files $@ + ;; + + legal) + shift + exec /usr/local/bin/backup-legal $@ + ;; + + music) + shift + exec /usr/local/bin/backup-music $@ + ;; + + *) + /usr/bin/printf "Unknown command '%s'\n" "$1" + exit 1 + ;; + esac +done + diff --git a/backup-files b/backup-files new file mode 100755 index 0000000..989659e --- /dev/null +++ b/backup-files @@ -0,0 +1,85 @@ +#!/bin/bash + +TEMP_DIR=~ + +if [[ $# -eq 0 ]]; then + /usr/bin/printf "USAGE: backup files --bucket=BUCKET --name=remote/archive/name [OPTIONS] FILES\n" + exit 1 +fi + +source /usr/local/lib/mylib.bash + +bucket="" +remote_archive_name="" +remote_checksum_name="" +local_archive_name="" +local_checksum_name="" +positional=() +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) + /usr/bin/printf "backup files [OPTIONS]\n" + /usr/bin/printf "Options:\n" + /usr/bin/printf " -h, --help Show help text\n" + /usr/bin/printf " -b=BUCKET, --bucket=BUCKET Push files to remote bucket [docs|media|work]\n" + /usr/bin/printf " -n NAME, --name NAME Name of archive\n" + exit 0 + ;; + + -b=docs|--bucket=docs) + bucket="dominic-docs" + shift + ;; + + -b=media|--bucket=media) + bucket="dominic-media" + shift + ;; + + -b=work|--bucket=work) + bucket="dominic-work" + shift + ;; + + -b=*|--bucket=*) + /usr/bin/printf "Invalid bucket '%s'\n" "$1"; + exit 1 + ;; + + -n|--name) + base_name="$(fn_basename "$2")" + safe_name="$(fn_basename "$2" | sed -e 's/\//_/g')" + + remote_archive_name="${base_name}.tar.zstd" + remote_checksum_name="${base_name}.sha256" + local_archive_name=${TEMP_DIR}/"${safe_name}.tar.zstd" + local_checksum_name=${TEMP_DIR}/"${safe_name}.sha256" + shift; shift + ;; + + *) + positional+=("$1") + shift + ;; + esac +done + +# error if no filenames given, or if no bucket given, or if no remote name given +if [[ "${#positional[@]}" -lt 1 ]]; then + /usr/bin/printf "No input filenames given\n" + exit 1 +elif [[ -z "$bucket" ]]; then + /usr/bin/printf "No remote bucket given\n" + exit 1 +elif [[ -z "$remote_archive_name" ]]; then + /usr/bin/printf "No remote filename given\n" + exit 1 +fi + +# main routine +/usr/local/bin/mktar --compress=zstd --checksum=sha256 --name "$local_archive_name" "${positional[@]}" \ + && ~/.local/bin/b2 upload-file "$bucket" "$local_archive_name" "$remote_archive_name" >/dev/null\ + && ~/.local/bin/b2 upload-file "$bucket" "$local_checksum_name" "$remote_checksum_name" >/dev/null\ + && /usr/bin/rm --force "$local_archive_name" \ + && /usr/bin/rm --force "$local_checksum_name" + diff --git a/backup-legal b/backup-legal new file mode 100755 index 0000000..1921f36 --- /dev/null +++ b/backup-legal @@ -0,0 +1,84 @@ +#!/bin/bash + +CACHE_DIR=~/.cache/backup-legal +LEGAL_DIR=/hdd/documents/legal +TEMP_DIR=~ + +if [[ $# -eq 0 ]]; then + /usr/bin/printf "USAGE: backup legal [OPTIONS]\n" + exit 1 +fi + +source /usr/local/lib/mylib.bash + +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) + /usr/bin/printf "backup legal [OPTIONS]\n" + /usr/bin/printf "Options:\n" + /usr/bin/printf " -h, --help Show help text\n" + /usr/bin/printf " -p, --push Push new documents to backups\n" + /usr/bin/printf " -u, --update Update cache of backups\n" + exit 0 + ;; + + -u|--update) + /usr/bin/printf "Updating local cache of legal documents on backup server...\n" + + /usr/bin/mkdir -p "$CACHE_DIR" + cd "$CACHE_DIR" + /usr/bin/rm * + ~/.local/bin/b2 ls --recursive dominic-docs legal \ + | /usr/bin/grep -e '\.tar\.zstd\.age$' \ + | /usr/bin/sed -e 's/\.tar\.zstd\.age//' -e 's/^legal\///' -e 's/\//-/' \ + | /usr/bin/uniq \ + | /usr/bin/xargs /usr/bin/touch + exit 0 + ;; + + -p|--push) + /usr/bin/printf "Pushing new legal documents to the backup server...\n" + + /usr/bin/mkdir -p "$CACHE_DIR" + + skipped=0 + + /usr/bin/printf "Enter a passphrase: " + read -s passphrase + /usr/bin/printf "\n" + + for doc_name in $(/usr/bin/find "${LEGAL_DIR}" -mindepth 1 -maxdepth 1); do + doc_name="$(/usr/bin/basename "$doc_name")" + base_name="$(fn_basename "$doc_name")" + + if [ -f "$CACHE_DIR/${base_name}" ]; then + #/usr/bin/printf "Skipping %s...\n" "$base_name" + + skipped=$((skipped+1)) + else + #/usr/bin/printf "Pushing %s...\n" "$base_name" + + cd "${LEGAL_DIR}" \ + && /usr/local/bin/mktar-batch --compress=zstd --checksum=sha256 --encrypt=age --passphrase "$passphrase" --name ${TEMP_DIR}/${base_name}.tar.zstd.age ${doc_name} \ + && ~/.local/bin/b2 upload-file dominic-docs ${TEMP_DIR}/${base_name}.tar.zstd.age legal/${base_name}.tar.zstd.age >/dev/null \ + && ~/.local/bin/b2 upload-file dominic-docs ${TEMP_DIR}/${base_name}.sha256 legal/${base_name}.sha256 >/dev/null \ + && /usr/bin/touch "${CACHE_DIR}/${base_name}" + + /usr/bin/rm --force ${TEMP_DIR}/${base_name}.tar.zstd.age + /usr/bin/rm --force ${TEMP_DIR}/${base_name}.sha256 + fi + done + + if [[ $skipped -ne 0 ]]; then + /usr/bin/printf "Skipped %s documents\n" "$skipped" + fi + exit 0 + ;; + + *) + /usr/bin/printf "Unknown option '%s'\n" "$1" + exit 1 + ;; + esac +done + diff --git a/backup-music b/backup-music new file mode 100755 index 0000000..3ac6e79 --- /dev/null +++ b/backup-music @@ -0,0 +1,85 @@ +#!/bin/bash + +CACHE_DIR=~/.cache/backup-music +MUSIC_DIR=/hdd/media/music +TEMP_DIR=~ + +if [[ $# -eq 0 ]]; then + /usr/bin/printf "USAGE: backup music [OPTIONS]\n" + exit 1 +fi + +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) + /usr/bin/printf "backup music [OPTIONS]\n" + /usr/bin/printf "Options:\n" + /usr/bin/printf " -h, --help Show help text\n" + /usr/bin/printf " -p, --push Push new music to backups\n" + /usr/bin/printf " -u, --update Update cache of backups\n" + exit 0 + ;; + + -u|--update) + /usr/bin/printf "Updating local cache of music on backup server...\n" + + /usr/bin/mkdir -p "$CACHE_DIR" + cd "$CACHE_DIR" + /usr/bin/rm * + ~/.local/bin/b2 ls --recursive dominic-media music \ + | /usr/bin/grep -e '\.tar\.gz\.gpg$' \ + | /usr/bin/sed -e 's/\.tar\.gz\.gpg//' -e 's/^music\///' -e 's/\//-/' \ + | /usr/bin/uniq \ + | /usr/bin/xargs /usr/bin/touch + exit 0 + ;; + + -p|--push) + /usr/bin/printf "Pushing new music to the backup server...\n" + + /usr/bin/mkdir -p "$CACHE_DIR" + + skipped=0 + + /usr/bin/printf "Enter a passphrase: " + read -s passphrase + /usr/bin/printf "\n" + + for artist in $(/usr/bin/find "${MUSIC_DIR}" -mindepth 1 -maxdepth 1 -type d); do + artist=$(/usr/bin/basename "$artist") + + for album in $(/usr/bin/find "${MUSIC_DIR}/${artist}" -mindepth 1 -maxdepth 1 -type d); do + album=$(/usr/bin/basename "$album") + name="${artist}-${album}" + if [ -f "$CACHE_DIR/${name}" ]; then + #/usr/bin/printf "Skipping %s...\n" "$name" + + skipped=$((skipped+1)) + else + #/usr/bin/printf "Pushing %s...\n" "$name" + + cd "${MUSIC_DIR}" \ + && /usr/local/bin/mktar-batch --compress=gzip --checksum=sha1 --encrypt=gpg --passphrase "$passphrase" --name ${TEMP_DIR}/${name}.tar.gz.gpg ${artist}/${album} \ + && ~/.local/bin/b2 upload-file dominic-media ${TEMP_DIR}/${name}.tar.gz.gpg music/${artist}/${album}.tar.gz.gpg >/dev/null \ + && ~/.local/bin/b2 upload-file dominic-media ${TEMP_DIR}/${name}.sha1 music/${artist}/${album}.sha1 >/dev/null \ + && /usr/bin/touch "${CACHE_DIR}/${name}" + + /usr/bin/rm --force ${TEMP_DIR}/${name}.tar.gz.gpg + /usr/bin/rm --force ${TEMP_DIR}/${name}.sha1 + fi + done + done + + if [[ $skipped -ne 0 ]]; then + /usr/bin/printf "Skipped %s albums\n" "$skipped" + fi + exit 0 + ;; + + *) + /usr/bin/printf "Unknown option '%s'\n" "$1" + exit 1 + ;; + esac +done + -- 2.45.2