diff --git a/deploy/push.sh b/deploy/push.sh index a4d8bc7..b3ad0e5 100755 --- a/deploy/push.sh +++ b/deploy/push.sh @@ -79,7 +79,15 @@ $TAR -C "$REPO/client/build" . | sh_ "tar xzf - -C '$STATIC'" # Hence sudo, matching how the service actually runs. SUDO="echo '$PASS' | sudo -S" echo "==> restart (sudo: the service runs as root, started at boot)" -BEFORE=$(sh_ "pgrep -f '$APP/backend/.venv/bin/gunicorn' | tr '\n' ',' " || true) +# DSM has no pgrep, and an unprivileged `ps` cannot see a root-owned process +# — either one silently returns nothing, which would make the pid comparison +# below always "pass" and put the check right back where it started. +pids_() { + sh_ "echo '$PASS' | sudo -S ps -eo pid,args 2>/dev/null \ + | grep '$APP/backend/.venv/bin/gunicorn' | grep -v grep \ + | awk '{print \$1}' | sort -n | tr '\n' ','" +} +BEFORE=$(pids_ || true) sh_ "cd '$APP' && $SUDO sh deploy/stop.sh >/dev/null 2>&1; sleep 3; $SUDO sh deploy/start.sh" \ || { echo "restart failed" >&2; exit 1; } @@ -89,8 +97,13 @@ sh_ "curl -sf -m 5 -o /dev/null -w 'local api: %{http_code}\n' \ # A 200 alone proves nothing: it is exactly what a surviving old master # returns. The master pid must have changed for the new code to be loaded. -AFTER=$(sh_ "pgrep -f '$APP/backend/.venv/bin/gunicorn' | tr '\n' ',' " || true) -if [ -n "$BEFORE" ] && [ "$BEFORE" = "$AFTER" ]; then +AFTER=$(pids_ || true) +if [ -z "$AFTER" ]; then + echo "cannot see any gunicorn process - the pid check could not run." >&2 + echo "Verify by hand before trusting this deploy." >&2 + exit 1 +fi +if [ "$BEFORE" = "$AFTER" ]; then echo "the gunicorn pids did not change ($AFTER) - the old process is still" >&2 echo "serving and your changes are NOT live. Check $APP/logs/error.log." >&2 exit 1 diff --git a/deploy/start.sh b/deploy/start.sh index 536d538..ae2f553 100755 --- a/deploy/start.sh +++ b/deploy/start.sh @@ -11,9 +11,14 @@ GUNICORN="$APP/backend/.venv/bin/gunicorn" # the new master then started, reported success, and served nothing — the # site was down while every log line looked normal. "$APP/deploy/stop.sh" >/dev/null 2>&1 + +# `ps | grep`, not pgrep: DSM has no pgrep, so this loop used to fail with 127 +# every second and wait the full 20s whether or not anything was still running. +alive() { ps -eo args 2>/dev/null | grep -q "^$GUNICORN"; } + i=0 while [ $i -lt 20 ]; do - pgrep -f "$GUNICORN" >/dev/null 2>&1 || break + alive || break sleep 1 i=$((i + 1)) done diff --git a/deploy/stop.sh b/deploy/stop.sh index 485c49a..f8da08d 100755 --- a/deploy/stop.sh +++ b/deploy/stop.sh @@ -9,9 +9,16 @@ fi # The master's workers do not always go with it, and a surviving worker keeps # :8124 bound — which looks exactly like a healthy start that serves nothing. +# +# `ps | grep` rather than pgrep: DSM does not ship pgrep, so the original +# check failed with 127 on every iteration — never matching the `|| exit 0` +# early return, always burning the full 15 seconds, and never actually +# confirming anything. +alive() { ps -eo args 2>/dev/null | grep -q "^$GUNICORN"; } + i=0 while [ $i -lt 15 ]; do - pgrep -f "$GUNICORN" >/dev/null 2>&1 || exit 0 + alive || exit 0 sleep 1 i=$((i + 1)) done