diff --git a/README.md b/README.md index 05fafe4..aeda05d 100644 --- a/README.md +++ b/README.md @@ -481,6 +481,18 @@ The SSH keypair needed no special handling: Unraid already auto-mirrors verifies the result is a real mountpoint (`mountpoint -q`) before writing anything — refuses to run rather than risk silently dumping backups onto the array if the disk is unplugged or fails to mount. +- **Unmounts it again when done — but only if this run is the one that + mounted it.** Checks the mount state *before* mounting and remembers it; + if the disk was already mounted for some other reason, this script + leaves it mounted afterward rather than pulling it out from under + whatever else was using it. Handled via an `EXIT` trap so it fires + reliably on any exit path, not just success. One gotcha found while + testing this: the script itself `cd`s into the mounted directory, so + without explicitly `cd`ing back out first, the unmount would fail with + "target is busy" (the shell's own working directory still being on the + device it's trying to unmount). Verified both directions: already + mounted → stays mounted after; not mounted → gets mounted, used, and + unmounted again, with no "busy" error. **Restore path, if ever needed**: manual and deliberate — stop the target Gitea container, unpack the chosen dump's DB/repos/etc. into `/data` per diff --git a/scripts/clients/vlda-01/README.md b/scripts/clients/vlda-01/README.md index bfa7035..c429ccf 100644 --- a/scripts/clients/vlda-01/README.md +++ b/scripts/clients/vlda-01/README.md @@ -39,7 +39,7 @@ of every script here, so it's worth stating plainly before anything else: | File here | Deployed path | Purpose | |---|---|---| -| `user-scripts/gitea-backup-pull/script` | `/boot/config/plugins/user.scripts/scripts/gitea-backup-pull/script` | Pulls new `gitea-dump` archives from `alpha` via the restricted `giteabackup` SFTP account, verifies each one's sha256 checksum, deletes both files on `alpha` only after a confirmed match, prunes its own local retention (30). Resolves and mounts the `WSD2L840` Unassigned Device itself first — see the script's own header comment for the full reasoning. | +| `user-scripts/gitea-backup-pull/script` | `/boot/config/plugins/user.scripts/scripts/gitea-backup-pull/script` | Pulls new `gitea-dump` archives from `alpha` via the restricted `giteabackup` SFTP account, verifies each one's sha256 checksum, deletes both files on `alpha` only after a confirmed match, prunes its own local retention (30). Resolves and mounts the `WSD2L840` Unassigned Device itself first, and unmounts it again afterward — but only if this run is the one that mounted it, never disturbing a mount it found already in place. See the script's own header comment for the full reasoning. | | `user-scripts/gitea-backup-pull/description` | `.../gitea-backup-pull/description` | Shown in the User Scripts UI. | | `user-scripts/gitea-backup-pull-onboot/script` | `.../gitea-backup-pull-onboot/script` | One-line wrapper: `bash`-invokes the script above. Exists only because `schedule.json` supports one schedule per script *path* — this is how the "also run once at every restart" requirement was added alongside the existing daily `03:30` schedule without disturbing it. | | `user-scripts/gitea-backup-pull-onboot/description` | `.../gitea-backup-pull-onboot/description` | Shown in the User Scripts UI. | diff --git a/scripts/clients/vlda-01/user-scripts/gitea-backup-pull/script b/scripts/clients/vlda-01/user-scripts/gitea-backup-pull/script index d0ea903..f18ba3d 100644 --- a/scripts/clients/vlda-01/user-scripts/gitea-backup-pull/script +++ b/scripts/clients/vlda-01/user-scripts/gitea-backup-pull/script @@ -16,6 +16,9 @@ # guaranteed to already be mounted - this script mounts it itself first # and refuses to proceed if that didn't actually result in a real # mountpoint, rather than risk silently writing backups onto the array. +# Unmounts it again once done, but only if this run is the one that +# mounted it - never unmounts a disk something else already had mounted +# for its own reasons. set -u KEY=/root/.ssh/gitea-backup/id_ed25519 @@ -38,6 +41,9 @@ if [ -z "$UD_DEV" ]; then exit 1 fi +UD_ALREADY_MOUNTED=false +mountpoint -q "$UD_MOUNTPOINT" && UD_ALREADY_MOUNTED=true + /usr/local/sbin/rc.unassigned mount "$UD_DEV" >/dev/null 2>&1 if ! mountpoint -q "$UD_MOUNTPOINT"; then @@ -45,6 +51,20 @@ if ! mountpoint -q "$UD_MOUNTPOINT"; then exit 1 fi +GET_BATCH=$(mktemp) +DEL_BATCH=$(mktemp) +cleanup() { + rm -f "$GET_BATCH" "$DEL_BATCH" + if [ "$UD_ALREADY_MOUNTED" = false ]; then + # cd out first - if the shell's own cwd is still on the device + # (it is, after the "cd $LOCAL_DIR" below), umount fails with + # "target is busy" + cd / || true + /usr/local/sbin/rc.unassigned umount "$UD_DEV" >/dev/null 2>&1 + fi +} +trap cleanup EXIT + mkdir -p "$LOCAL_DIR" SFTP="sftp -P $REMOTE_PORT -i $KEY -o UserKnownHostsFile=$KNOWN_HOSTS -o BatchMode=yes" @@ -56,10 +76,6 @@ if [ -z "$REMOTE_LISTING" ]; then fi REMOTE_ZIPS=$(echo "$REMOTE_LISTING" | grep '\.zip$') -GET_BATCH=$(mktemp) -DEL_BATCH=$(mktemp) -trap 'rm -f "$GET_BATCH" "$DEL_BATCH"' EXIT - TO_FETCH=0 while read -r fname; do [ -z "$fname" ] && continue