From f414a988b8c78965adf8cabdf5ad935d594d1a84 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Tue, 14 Jul 2026 22:02:30 +0200 Subject: [PATCH] fix(scripts): auto-switch dev.port when it's already in use flushall_build_and_run.sh and flushall_fast_build_and_run.sh always started the HTTP4S server on the configured dev.port (default 8080). If that port was already bound by another local process (e.g. another OBP-API instance), the new server failed to bind or the caller had no way to know a fallback was needed. Both scripts now probe the port before starting the server and, if busy, walk forward to the next free port in a 50-port range, exporting it via OBP_DEV_PORT (APIUtil.getPropsValue checks env vars before props, so this requires no props-file change) and printing "PORT: " alongside the existing "PID: " line. Also fixes a hang in flushall_build_and_run.sh's background mode: it launched java with `> >(tee "$RUNTIME_LOG") 2>&1`, a process substitution whose inner tee inherits the script's own stdout fd. When this script is invoked from a caller that captures its output via command substitution piped through tee (e.g. `out=$(./flushall_build_and_run.sh --background 2>&1 | tee /dev/stderr)`, the pattern smoke_test.sh uses), that inherited fd keeps the caller's pipe open for as long as the server runs, so the command substitution never returns even though the meaningful output already printed. Switched to a plain file redirect (matching flushall_fast_build_and_run.sh, which never had this problem), so the script's own file descriptors close cleanly on exit regardless of the backgrounded server's lifetime. --- flushall_build_and_run.sh | 41 ++++++++++++++++++++++++++++++---- flushall_fast_build_and_run.sh | 27 ++++++++++++++++++++++ 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/flushall_build_and_run.sh b/flushall_build_and_run.sh index 13a8bfa6c5..076d77d40c 100755 --- a/flushall_build_and_run.sh +++ b/flushall_build_and_run.sh @@ -128,6 +128,32 @@ echo "✓ JAR created: obp-api/target/obp-api.jar (thin jar — runtime deps in echo "✓ Build log saved to: build.log" echo "" +################################################################################ +# PICK A FREE PORT (auto-switch if the configured one is already in use) +################################################################################ + +# dev.port -> OBP_DEV_PORT env var (APIUtil.getPropsValue checks env before +# props, see Http4sServer.scala's getPropsAsIntValue("dev.port", 8080)), so +# exporting this here is enough to actually move the server off a busy port. +DEV_PORT="${OBP_DEV_PORT:-8080}" +if lsof -nP -iTCP:"$DEV_PORT" -sTCP:LISTEN >/dev/null 2>&1; then + ORIGINAL_PORT="$DEV_PORT" + FOUND_FREE_PORT=false + for candidate in $(seq $((DEV_PORT + 1)) $((DEV_PORT + 50))); do + if ! lsof -nP -iTCP:"$candidate" -sTCP:LISTEN >/dev/null 2>&1; then + DEV_PORT="$candidate" + FOUND_FREE_PORT=true + break + fi + done + if [ "$FOUND_FREE_PORT" = false ]; then + echo "❌ Port $ORIGINAL_PORT is already in use and no free port was found in $((ORIGINAL_PORT + 1))-$((ORIGINAL_PORT + 50))." + exit 1 + fi + echo "⚠ Port $ORIGINAL_PORT is already in use — switching to port $DEV_PORT" +fi +export OBP_DEV_PORT="$DEV_PORT" + ################################################################################ # RUN HTTP4S SERVER ################################################################################ @@ -138,6 +164,7 @@ if [ "$RUN_BACKGROUND" = true ]; then else echo "Starting HTTP4S server (foreground)..." fi +echo " PORT: $DEV_PORT" echo "==========================================" # Java options for runtime @@ -155,15 +182,21 @@ JAVA_OPTS="--add-opens java.base/java.lang=ALL-UNNAMED \ RUNTIME_LOG=/tmp/obp-api.log if [ "$RUN_BACKGROUND" = true ]; then - # Run in background with output to log file (tee'd to /tmp as well) - nohup java $JAVA_OPTS -jar obp-api/target/obp-api.jar > >(tee "$RUNTIME_LOG") 2>&1 & + # Run in background with output to log file. Redirect straight to the file + # (not `> >(tee "$RUNTIME_LOG")`): that process-substitution form spawns a + # `tee` that inherits this script's own stdout fd, which — when this script + # is itself invoked from a caller capturing output via `$(... | tee ...)` + # (e.g. smoke_test.sh's start_and_test) — keeps that caller's pipe open for + # as long as the server runs, so `$(...)` never returns. A plain file + # redirect closes cleanly with this script's own exit. + nohup java $JAVA_OPTS -jar obp-api/target/obp-api.jar > "$RUNTIME_LOG" 2>&1 & SERVER_PID=$! echo "✓ HTTP4S server started in background" echo " PID: $SERVER_PID" - echo " Log: http4s-server.log (also $RUNTIME_LOG)" + echo " Log: $RUNTIME_LOG" echo "" echo "To stop the server: kill $SERVER_PID" - echo "To view logs: tail -f http4s-server.log" + echo "To view logs: tail -f $RUNTIME_LOG" else # Run in foreground (Ctrl+C to stop). Also tee output to /tmp so it can be # tailed from another terminal without taking over this one. diff --git a/flushall_fast_build_and_run.sh b/flushall_fast_build_and_run.sh index 88669ab6e9..077cea3c03 100755 --- a/flushall_fast_build_and_run.sh +++ b/flushall_fast_build_and_run.sh @@ -296,6 +296,32 @@ echo "✓ JAR created: obp-api/target/obp-api.jar (thin jar — runtime deps in echo "✓ Build log saved to: fast_build.log" echo "" +################################################################################ +# PICK A FREE PORT (auto-switch if the configured one is already in use) +################################################################################ + +# dev.port -> OBP_DEV_PORT env var (APIUtil.getPropsValue checks env before +# props, see Http4sServer.scala's getPropsAsIntValue("dev.port", 8080)), so +# exporting this here is enough to actually move the server off a busy port. +DEV_PORT="${OBP_DEV_PORT:-8080}" +if lsof -nP -iTCP:"$DEV_PORT" -sTCP:LISTEN >/dev/null 2>&1; then + ORIGINAL_PORT="$DEV_PORT" + FOUND_FREE_PORT=false + for candidate in $(seq $((DEV_PORT + 1)) $((DEV_PORT + 50))); do + if ! lsof -nP -iTCP:"$candidate" -sTCP:LISTEN >/dev/null 2>&1; then + DEV_PORT="$candidate" + FOUND_FREE_PORT=true + break + fi + done + if [ "$FOUND_FREE_PORT" = false ]; then + echo "❌ Port $ORIGINAL_PORT is already in use and no free port was found in $((ORIGINAL_PORT + 1))-$((ORIGINAL_PORT + 50))." + exit 1 + fi + echo "⚠ Port $ORIGINAL_PORT is already in use — switching to port $DEV_PORT" +fi +export OBP_DEV_PORT="$DEV_PORT" + ################################################################################ # RUN HTTP4S SERVER ################################################################################ @@ -306,6 +332,7 @@ if [ "$RUN_BACKGROUND" = true ]; then else echo "Starting HTTP4S server (foreground)..." fi +echo " PORT: $DEV_PORT" echo "==========================================" # Java options for runtime