|
|
|
@@ -79,6 +79,53 @@ running_pid() { pgrep -f "$PATTERN" || true; }
|
|
|
|
|
launchd_installed() { [ -f "$LAUNCHD_PLIST" ]; }
|
|
|
|
|
launchd_loaded() { launchctl list "$LAUNCHD_LABEL" >/dev/null 2>&1; }
|
|
|
|
|
|
|
|
|
|
# CB-600: the script computes its own log path from where it sits on disk (REPO, above); the
|
|
|
|
|
# plist hard-codes an absolute StandardOutPath. Nothing forced the two to agree — if this script
|
|
|
|
|
# were ever run from a checkout other than the one the loaded plist names, launchd would start and
|
|
|
|
|
# log the daemon correctly, while every check below (the fresh "bridged listening" line, the
|
|
|
|
|
# ERROR-count scan) would read a different, empty or stale file and the script would report a
|
|
|
|
|
# clean restart while the daemon crash-loops. Pure and side-effect-free besides `die`/`ok` — reads
|
|
|
|
|
# the two paths, resolves them, compares — so it never touches launchd or the daemon and can be
|
|
|
|
|
# exercised by sourcing this script (see the SOURCED guard below) without installing the agent.
|
|
|
|
|
check_log_path_matches_plist() {
|
|
|
|
|
local script_out="$1" plist_path="$2"
|
|
|
|
|
local plist_out resolved_out resolved_plist_out
|
|
|
|
|
# Checked by exit status, not by emptiness: on a missing file/key PlistBuddy exits nonzero but
|
|
|
|
|
# still writes a message ("File Doesn't Exist, Will Create: ...") that command substitution
|
|
|
|
|
# would happily capture as if it were the real value — testing only `-z` missed that case.
|
|
|
|
|
if ! plist_out="$(/usr/libexec/PlistBuddy -c 'Print :StandardOutPath' "$plist_path" 2>/dev/null)" \
|
|
|
|
|
|| [ -z "$plist_out" ]; then
|
|
|
|
|
die "launchd agent is loaded but PlistBuddy could not read StandardOutPath from
|
|
|
|
|
$plist_path
|
|
|
|
|
— cannot verify the daemon logs where this script is about to look. Fix the plist before
|
|
|
|
|
redeploying supervised."
|
|
|
|
|
fi
|
|
|
|
|
resolved_out="$(cd "$(dirname "$script_out")" 2>/dev/null && pwd -P)/$(basename "$script_out")" || true
|
|
|
|
|
resolved_plist_out="$(cd "$(dirname "$plist_out")" 2>/dev/null && pwd -P)/$(basename "$plist_out")" || true
|
|
|
|
|
if [ -z "$resolved_out" ] || [ -z "$resolved_plist_out" ] || [ "$resolved_out" != "$resolved_plist_out" ]; then
|
|
|
|
|
die "log path mismatch — this script reads
|
|
|
|
|
$script_out (resolved: ${resolved_out:-<directory does not exist>})
|
|
|
|
|
but the loaded plist's StandardOutPath is
|
|
|
|
|
$plist_out (resolved: ${resolved_plist_out:-<directory does not exist>})
|
|
|
|
|
Under supervision the daemon writes to the PLIST's path, not necessarily this script's — every
|
|
|
|
|
post-restart check below (the fresh 'bridged listening' line, the ERROR-count scan) would read
|
|
|
|
|
the wrong file and could report a clean restart while the daemon crash-loops. Fix the mismatch
|
|
|
|
|
(move this checkout to match the plist, or edit the plist's StandardOutPath/StandardErrorPath)
|
|
|
|
|
before redeploying supervised."
|
|
|
|
|
fi
|
|
|
|
|
ok "log path check: script and plist agree ($resolved_out)"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# CB-600: sourceable for testing. When this file is SOURCED (not executed) it stops here — nothing
|
|
|
|
|
# below runs — so a test harness can `source` it to call check_log_path_matches_plist (or the
|
|
|
|
|
# other pure helpers above) against a throwaway plist fixture without ever reaching the mutating
|
|
|
|
|
# flow (build/stop/start) or touching the real daemon or launchd. On a normal `./redeploy-bridged.sh`
|
|
|
|
|
# invocation `(return 0 2>/dev/null)` fails (return is illegal at top level of an executed script),
|
|
|
|
|
# so this whole block is a no-op and every line below still runs exactly as before.
|
|
|
|
|
if (return 0 2>/dev/null); then
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------- report state
|
|
|
|
|
|
|
|
|
|
say "current state"
|
|
|
|
@@ -103,6 +150,9 @@ SUPERVISED=0
|
|
|
|
|
if launchd_loaded; then
|
|
|
|
|
SUPERVISED=1
|
|
|
|
|
ok "launchd agent loaded ($LAUNCHD_LABEL) — launchd supervises this daemon"
|
|
|
|
|
# CB-600: fail loudly here, before ANY other check runs, if this script and the loaded plist
|
|
|
|
|
# would read different log files — every check after this point is worthless otherwise.
|
|
|
|
|
check_log_path_matches_plist "$OUT" "$LAUNCHD_PLIST"
|
|
|
|
|
else
|
|
|
|
|
warn "launchd agent not loaded — this script is the only thing that will restart the daemon."
|
|
|
|
|
fi
|
|
|
|
@@ -222,7 +272,22 @@ say "start"
|
|
|
|
|
if [ "$SUPERVISED" = 1 ]; then
|
|
|
|
|
echo " supervision is ON: using 'launchctl load' so launchd starts and keeps supervising this"
|
|
|
|
|
echo " process, instead of a manual nohup that launchd would know nothing about."
|
|
|
|
|
launchctl load -w "$LAUNCHD_PLIST" || die "launchctl load failed"
|
|
|
|
|
# CB-600: 'launchctl unload -w' above already persisted Disabled=true for this label. A load -w
|
|
|
|
|
# that succeeds clears it; a load -w that FAILS leaves the agent both stopped and disabled — worse
|
|
|
|
|
# than before this script ran, because a later reboot or login will not bring it back either. One
|
|
|
|
|
# retry covers a transient race (e.g. launchd not yet fully done deregistering); if it still fails,
|
|
|
|
|
# die with the exact recovery command rather than a bare "failed".
|
|
|
|
|
if ! launchctl load -w "$LAUNCHD_PLIST" 2>/dev/null; then
|
|
|
|
|
warn "launchctl load failed on the first attempt — retrying once after a short pause"
|
|
|
|
|
sleep 2
|
|
|
|
|
launchctl load -w "$LAUNCHD_PLIST" || die "launchctl load failed twice.
|
|
|
|
|
The agent is now STOPPED and DISABLED — it will NOT come back on its own, not even after a
|
|
|
|
|
reboot or login, because 'launchctl unload -w' above persisted Disabled=true and load -w
|
|
|
|
|
never got the chance to clear it. Recover with:
|
|
|
|
|
launchctl load -w \"$LAUNCHD_PLIST\"
|
|
|
|
|
If that still fails, check 'launchctl list $LAUNCHD_LABEL', validate the plist with
|
|
|
|
|
'plutil -lint \"$LAUNCHD_PLIST\"', and check $OUT before assuming a retry will succeed."
|
|
|
|
|
fi
|
|
|
|
|
else
|
|
|
|
|
# Absolute jar path so `ps` names which checkout is running.
|
|
|
|
|
( cd "$BRIDGED" && zsh -lc "nohup java -jar '$JAR' >> bridged.out 2>&1 &" )
|
|
|
|
|