From 97f968a30e7dc28f6d99bfbaae8a4aeefb6ad525 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Fri, 23 Jan 2026 12:48:30 +0100 Subject: added all of my scripts --- backup_usb.sh | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100755 backup_usb.sh (limited to 'backup_usb.sh') diff --git a/backup_usb.sh b/backup_usb.sh new file mode 100755 index 0000000..8c81b69 --- /dev/null +++ b/backup_usb.sh @@ -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/ +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.)" + -- cgit v1.3