diff options
| author | Lukasz Kasprzak <lukasz.kasprzak@pm.me> | 2026-02-17 16:20:40 +0100 |
|---|---|---|
| committer | Lukasz Kasprzak <lukasz.kasprzak@pm.me> | 2026-02-17 16:20:40 +0100 |
| commit | c74163f1ecbd809c83bb465ee89fa04369a89972 (patch) | |
| tree | c1a52692a47566652d7f2a9a8eceb9f1839991b7 /usb-backup | |
| parent | 70e6d80c2d367480478eacf46363ee88a0e994ff (diff) | |
| download | bin-c74163f1ecbd809c83bb465ee89fa04369a89972.tar.gz bin-c74163f1ecbd809c83bb465ee89fa04369a89972.zip | |
cleaned up names and dir
Diffstat (limited to 'usb-backup')
| -rwxr-xr-x | usb-backup | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/usb-backup b/usb-backup new file mode 100755 index 0000000..8c81b69 --- /dev/null +++ b/usb-backup @@ -0,0 +1,155 @@ +#!/usr/bin/env bash +set -euo pipefail + +#################### CONFIG #################### + +# LUKS2 container UUID (LUKS header UUID) +LUKS_SOURCE="/dev/disk/by-uuid/bdd2a016-b6db-493d-ad0a-e8dd8a93dfbd" + +# Name for /dev/mapper/<name> +MAPPER_NAME="usb_safe" + +# Mountpoint for decrypted filesystem +MOUNTPOINT="/mnt/usb_safe" + +# Optional underlying block device for power-off (set "" to disable) +RAW_DEVICE="" + +# Items to mirror from $HOME to the encrypted drive (files and directories) +BACKUP_ITEMS=( + "$HOME/.abook" + "$HOME/.config" + "$HOME/Documents" + "$HOME/dotfiles" + "$HOME/.password-store" + "$HOME/secure" + "$HOME/vimwiki" + "$HOME/.password.tomb" + "$HOME/.secrets.tomb" +) + +RSYNC_OPTS=( + -a + --delete + --no-perms + --no-owner + --no-group + --no-xattrs + --omit-dir-times + --progress +) + +LOGFILE="$HOME/backup_flash_rsync.log" + +#################### HELPERS #################### + +die() { echo "ERROR: $*" >&2; exit 1; } + +is_mapper_open() { [[ -e "/dev/mapper/${MAPPER_NAME}" ]]; } +is_mounted() { mountpoint -q "${MOUNTPOINT}"; } + +busy_report() { + echo ">>> Busy report for ${MOUNTPOINT}:" + echo ">>> lsof:" + sudo lsof +f -- "${MOUNTPOINT}" || true + echo ">>> fuser:" + sudo fuser -vm "${MOUNTPOINT}" || true +} + +cleanup() { + set +e + + if is_mounted; then + echo ">>> Unmounting ${MOUNTPOINT}..." + sudo umount "${MOUNTPOINT}" || { + echo ">>> Unmount failed (device busy)." + busy_report + echo ">>> Last resort: sudo umount -l '${MOUNTPOINT}'" + } + fi + + if is_mapper_open; then + echo ">>> Closing LUKS mapper ${MAPPER_NAME}..." + sudo cryptsetup close "${MAPPER_NAME}" || true + fi + + if [[ -n "${RAW_DEVICE}" ]]; then + echo ">>> Powering off ${RAW_DEVICE}..." + udisksctl power-off -b "${RAW_DEVICE}" >/dev/null 2>&1 || true + fi +} + +trap cleanup EXIT + +#################### OPEN + MOUNT #################### + +echo ">>> Checking LUKS source exists: ${LUKS_SOURCE}" +[[ -e "${LUKS_SOURCE}" ]] || die "LUKS source not found: ${LUKS_SOURCE}" + +echo ">>> Ensuring mountpoint exists: ${MOUNTPOINT}" +sudo mkdir -p "${MOUNTPOINT}" + +is_mounted && die "Mountpoint already in use: ${MOUNTPOINT}" +is_mapper_open && die "Mapper already open: /dev/mapper/${MAPPER_NAME}" + +echo ">>> Opening LUKS2 container (prompt for passphrase)..." +sudo cryptsetup open --type luks2 "${LUKS_SOURCE}" "${MAPPER_NAME}" + +echo ">>> Mounting decrypted filesystem..." +sudo mount "/dev/mapper/${MAPPER_NAME}" "${MOUNTPOINT}" + +echo ">>> Mounted at ${MOUNTPOINT}" +echo ">>> Logging rsync output to: ${LOGFILE}" +echo "[$(date)] Backup run started" >> "${LOGFILE}" + +#################### RSYNC LOOP #################### + +ANY_WARNING=0 + +for SRC in "${BACKUP_ITEMS[@]}"; do + [[ -e "${SRC}" ]] || die "Missing source item: ${SRC}" + + NAME="$(basename "${SRC}")" + DEST="${MOUNTPOINT}/${NAME}" + + echo ">>> rsync: ${SRC} -> ${DEST}" + echo "[$(date)] rsync: ${SRC} -> ${DEST}" >> "${LOGFILE}" + + set +e + if [[ -d "${SRC}" ]]; then + rsync "${RSYNC_OPTS[@]}" "${SRC}/" "${DEST}/" 2>> "${LOGFILE}" + else + # file + rsync "${RSYNC_OPTS[@]}" "${SRC}" "${DEST}" 2>> "${LOGFILE}" + fi + RS=$? + set -e + + if [[ "${RS}" -eq 0 ]]; then + echo ">>> rsync OK: ${SRC}" + echo "[$(date)] rsync OK: ${SRC}" >> "${LOGFILE}" + elif [[ "${RS}" -eq 23 || "${RS}" -eq 24 ]]; then + echo ">>> WARNING: rsync non-critical issues (code ${RS}) for: ${SRC}" + echo ">>> See ${LOGFILE}." + echo "[$(date)] WARNING: rsync code ${RS} for: ${SRC}" >> "${LOGFILE}" + ANY_WARNING=1 + else + echo "[$(date)] ERROR: rsync failed code ${RS} for: ${SRC}" >> "${LOGFILE}" + exit "${RS}" + fi +done + +echo ">>> Backup loop finished." +if [[ "${ANY_WARNING}" -eq 1 ]]; then + echo ">>> Backup completed WITH WARNINGS. See ${LOGFILE}." + echo "[$(date)] Backup completed WITH WARNINGS" >> "${LOGFILE}" +else + echo ">>> Backup completed OK." + echo "[$(date)] Backup completed OK" >> "${LOGFILE}" +fi + +echo ">>> Syncing..." +sync + +echo ">>> Done. (Auto-cleanup will unmount + close mapper.)" + |
