From f75957130ed9b44380fabacac0717ea90b9d34ec Mon Sep 17 00:00:00 2001 From: Gmer4Lfe Date: Tue, 14 Jul 2026 18:29:53 -0400 Subject: [PATCH] Cap merge-pass pull with the same 23h timeout as the main push MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pull step (merge mode) had no timeout or bandwidth limit at all, so a slow/stalled pull could block the entire per-share sync indefinitely — and since daily_sync_maintenance.sh calls rsync.sh synchronously per share, that blocked every later share and all post-sync maintenance jobs too. RSYNC_MAX_RUNTIME_HOURS was only ever wired into the push half. --- Rsync/rsync.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Rsync/rsync.sh b/Rsync/rsync.sh index 7cd9e30..1d447e9 100755 --- a/Rsync/rsync.sh +++ b/Rsync/rsync.sh @@ -371,10 +371,10 @@ RSYNC_OPTS+=(--stats) # Runs before the push so anything the remote has that we don't is preserved locally. # After this pass, local is the superset — the delete push in pass 2 is then safe. if [[ "$MERGE_RUN" == true ]]; then - echo "$ICON_SYNC Merge pass 1 — pulling ${REMOTE_SERVER_NAME}-unique content to local..." + echo "$ICON_SYNC Merge pass 1 — pulling ${REMOTE_SERVER_NAME}-unique content to local (capped at ${RSYNC_MAX_RUNTIME_HOURS}h)..." _pull_opts=(-av --ignore-existing --stats) [[ "$DRY_RUN" == true ]] && _pull_opts+=(--dry-run) - _pull_output=$(rsync "${_pull_opts[@]}" \ + _pull_output=$(timeout "${RSYNC_MAX_RUNTIME_SECONDS}s" rsync "${_pull_opts[@]}" \ -e "ssh -i $SSH_KEY -T -o Compression=no -o IPQoS=throughput" \ "root@${REMOTE_SERVER}:${DIRECTORY}/" "${DIRECTORY}/" 2>&1) _pull_exit=$? @@ -382,6 +382,12 @@ if [[ "$MERGE_RUN" == true ]]; then awk '/Total transferred file size:/{gsub(/,/,"",$NF); gsub(/[^0-9]/,"",$NF); print $NF+0}') if [[ "$_pull_exit" -eq 0 ]]; then echo "$ICON_DONE Merge pass 1 complete — ${_pull_bytes:-0} bytes pulled" + elif [[ "$_pull_exit" -eq 124 ]]; then + # Same cap as the main push — never let one direction of the merge run unbounded. + # Files already completed before the timeout stay pulled; next scheduled run + # picks up whatever's still remote-unique (no --partial here, so an in-flight + # file at the moment of the kill is discarded, not corrupted). + warn "Merge pass 1 exceeded ${RSYNC_MAX_RUNTIME_HOURS}h cap — continuing with push, will resume pull next scheduled run" else warn "Merge pass 1 failed (exit $_pull_exit) — continuing with push" echo "$_pull_output" | grep -iE "error|rsync:|permission denied" | while read -r _line; do