Refactor backtunnel-share with cleanup logic, duration-based termination, and improved error handling; introduce backtunnel-share-gui for streamlined GUI-based operation

This commit is contained in:
2025-09-14 18:07:58 +02:00
parent 5dab6c08aa
commit 905bc24f78
3 changed files with 87 additions and 13 deletions

View File

@@ -5,7 +5,8 @@
# backtunnel-share: Share a folder using reverse SSH for a limited duration
# Syntax: backtunnel-share /path/to/folder with remoteuser:remotehost for 2h
# Options: -p|--tunnel-port <PORT> -l|--local-ssh-port <PORT> -i|--invite [--invite-mount <PATH>] [--invite-file <FILE>] [--qr] -h|--help
# Options: -p|--tunnel-port <PORT> -l|--local-ssh-port <PORT>
# -i|--invite [--invite-mount <PATH>] [--invite-file <FILE>] [--qr] -h|--help
set -euo pipefail
@@ -123,6 +124,7 @@ fi
# --- deps check ---
command -v ssh >/dev/null 2>&1 || { echo "ssh not found."; exit 1; }
command -v timeout >/dev/null 2>&1 || { echo "timeout not found."; exit 1; }
command -v tail >/dev/null 2>&1 || { echo "tail not found."; exit 1; } # used for --pid wait
echo "⏳ Sharing '${FOLDER}' via reverse SSH:"
echo " local sshd port : ${LOCAL_SSH_PORT}"
@@ -164,9 +166,10 @@ fi
echo "Tip: On the remote side, mount with:"
echo " backtunnel-access '${FOLDER}' from ${REMOTE_USER}@${REMOTE_HOST} -p ${TUNNEL_PORT}"
echo "To stop sharing early: press Ctrl+C here."
echo "Listener will appear on: ${REMOTE_HOST}:${TUNNEL_PORT} (run access there)."
echo "To stop sharing early: press Ctrl+C in this window."
# --- optional pre-flight: warn if remote loopback port is already in use (best-effort) ---
# --- optional pre-flight: warn if remote loopback port already in use (best-effort) ---
if ssh -o BatchMode=yes -o ConnectTimeout=5 "${REMOTE_USER}@${REMOTE_HOST}" \
"command -v nc >/dev/null 2>&1 && nc -z 127.0.0.1 ${TUNNEL_PORT}"; then
echo "⚠️ Port ${TUNNEL_PORT} on remote 127.0.0.1 appears in use; choose another with -p." >&2
@@ -174,19 +177,45 @@ if ssh -o BatchMode=yes -o ConnectTimeout=5 "${REMOTE_USER}@${REMOTE_HOST}" \
# exit 1
fi
# Bind reverse to 127.0.0.1 on the REMOTE host (private-by-default).
# Keepalive so the tunnel drops on dead links.
# Exit fast if the reverse bind fails (e.g., port in use).
timeout "$DURATION" ssh -N \
# --- run ssh in background; trap Ctrl-C/TERM/EXIT to stop it cleanly ---
SSH_PID=""
# shellcheck disable=SC2317 # cleanup is invoked indirectly via trap
cleanup() {
if [[ -n "${SSH_PID:-}" ]] && kill -0 "$SSH_PID" 2>/dev/null; then
echo "⏹️ Stopping share..."
kill -TERM "$SSH_PID" 2>/dev/null || true
# give ssh a moment to exit gracefully
wait "$SSH_PID" 2>/dev/null || true
fi
}
trap cleanup INT TERM EXIT
# Start reverse-tunnel ssh in background with keepalives + fast-fail on -R bind
ssh -N \
-o ExitOnForwardFailure=yes \
-o ServerAliveInterval=15 \
-o ServerAliveCountMax=3 \
-R "${TUNNEL_PORT}:localhost:${LOCAL_SSH_PORT}" \
-- "${REMOTE_USER}@${REMOTE_HOST}"
-- "${REMOTE_USER}@${REMOTE_HOST}" &
SSH_PID=$!
rc=$?
if [[ $rc -eq 124 ]]; then
echo "⏹️ Sharing ended: reached duration (${DURATION})."
# Wait for ssh to exit, but bounded by duration:
# Use 'timeout … tail --pid=PID -f /dev/null' so we don't need bash -c 'wait "$1"'
if timeout "$DURATION" tail --pid="$SSH_PID" -f /dev/null; then
# ssh exited on its own before timeout
exit 0
else
rc=$?
if [[ $rc -eq 124 ]]; then
echo "⏹️ Sharing ended: reached duration (${DURATION})."
# ensure the child is gone
if kill -0 "$SSH_PID" 2>/dev/null; then
kill -TERM "$SSH_PID" 2>/dev/null || true
wait "$SSH_PID" 2>/dev/null || true
fi
exit 0
fi
# other error from timeout/tail
exit "$rc"
fi
exit "$rc"