fix: add safer custom command path for run_overnight
All checks were successful
Gitea CI / test (push) Successful in 36s
Gitea CI / test (pull_request) Successful in 35s

This commit is contained in:
agentson
2026-03-04 02:36:24 +09:00
parent c412412f7b
commit dc0775cbc6
2 changed files with 30 additions and 4 deletions

View File

@@ -10,9 +10,20 @@ TMUX_ATTACH="${TMUX_ATTACH:-true}"
TMUX_SESSION_PREFIX="${TMUX_SESSION_PREFIX:-ouroboros_overnight}" TMUX_SESSION_PREFIX="${TMUX_SESSION_PREFIX:-ouroboros_overnight}"
STARTUP_GRACE_SEC="${STARTUP_GRACE_SEC:-3}" STARTUP_GRACE_SEC="${STARTUP_GRACE_SEC:-3}"
dashboard_port="${DASHBOARD_PORT:-8080}" dashboard_port="${DASHBOARD_PORT:-8080}"
APP_CMD_BIN="${APP_CMD_BIN:-}"
APP_CMD_ARGS="${APP_CMD_ARGS:-}"
RUNS_DASHBOARD="false"
if [ -z "${APP_CMD:-}" ]; then if [ -n "$APP_CMD_BIN" ]; then
USE_DEFAULT_APP_CMD="false"
USE_SAFE_CUSTOM_APP_CMD="true"
APP_CMD="${APP_CMD_BIN} ${APP_CMD_ARGS}"
if [[ " $APP_CMD_ARGS " == *" --dashboard "* ]]; then
RUNS_DASHBOARD="true"
fi
elif [ -z "${APP_CMD:-}" ]; then
USE_DEFAULT_APP_CMD="true" USE_DEFAULT_APP_CMD="true"
USE_SAFE_CUSTOM_APP_CMD="false"
if [ -x ".venv/bin/python" ]; then if [ -x ".venv/bin/python" ]; then
PYTHON_BIN=".venv/bin/python" PYTHON_BIN=".venv/bin/python"
elif command -v python3 >/dev/null 2>&1; then elif command -v python3 >/dev/null 2>&1; then
@@ -25,8 +36,13 @@ if [ -z "${APP_CMD:-}" ]; then
fi fi
APP_CMD="$PYTHON_BIN -m src.main --mode=live --dashboard" APP_CMD="$PYTHON_BIN -m src.main --mode=live --dashboard"
RUNS_DASHBOARD="true"
else else
USE_DEFAULT_APP_CMD="false" USE_DEFAULT_APP_CMD="false"
USE_SAFE_CUSTOM_APP_CMD="false"
if [[ "$APP_CMD" == *"--dashboard"* ]]; then
RUNS_DASHBOARD="true"
fi
fi fi
mkdir -p "$LOG_DIR" mkdir -p "$LOG_DIR"
@@ -64,7 +80,7 @@ if [ -f "$PID_FILE" ]; then
fi fi
echo "[$(date -u +"%Y-%m-%dT%H:%M:%SZ")] starting: $APP_CMD" | tee -a "$RUN_LOG" echo "[$(date -u +"%Y-%m-%dT%H:%M:%SZ")] starting: $APP_CMD" | tee -a "$RUN_LOG"
if [[ "$APP_CMD" == *"--dashboard"* ]] && is_port_in_use "$dashboard_port"; then if [ "$RUNS_DASHBOARD" = "true" ] && is_port_in_use "$dashboard_port"; then
echo "[$(date -u +"%Y-%m-%dT%H:%M:%SZ")] startup failed: dashboard port ${dashboard_port} already in use" | tee -a "$RUN_LOG" echo "[$(date -u +"%Y-%m-%dT%H:%M:%SZ")] startup failed: dashboard port ${dashboard_port} already in use" | tee -a "$RUN_LOG"
exit 1 exit 1
fi fi
@@ -72,6 +88,15 @@ fi
if [ "$USE_DEFAULT_APP_CMD" = "true" ]; then if [ "$USE_DEFAULT_APP_CMD" = "true" ]; then
# Default path avoids shell word-splitting on executable paths. # Default path avoids shell word-splitting on executable paths.
nohup env DASHBOARD_PORT="$dashboard_port" "$PYTHON_BIN" -m src.main --mode=live --dashboard >>"$RUN_LOG" 2>&1 & nohup env DASHBOARD_PORT="$dashboard_port" "$PYTHON_BIN" -m src.main --mode=live --dashboard >>"$RUN_LOG" 2>&1 &
elif [ "$USE_SAFE_CUSTOM_APP_CMD" = "true" ]; then
# Safer custom path: executable path is handled as a single token.
if [ -n "$APP_CMD_ARGS" ]; then
# shellcheck disable=SC2206
app_args=( $APP_CMD_ARGS )
nohup env DASHBOARD_PORT="$dashboard_port" "$APP_CMD_BIN" "${app_args[@]}" >>"$RUN_LOG" 2>&1 &
else
nohup env DASHBOARD_PORT="$dashboard_port" "$APP_CMD_BIN" >>"$RUN_LOG" 2>&1 &
fi
else else
# Custom APP_CMD is treated as a shell command string. # Custom APP_CMD is treated as a shell command string.
# If executable paths include spaces, they must be quoted inside APP_CMD. # If executable paths include spaces, they must be quoted inside APP_CMD.

View File

@@ -101,7 +101,8 @@ def test_run_overnight_writes_live_pid_and_watchdog_pid(tmp_path: Path) -> None:
"TMUX_AUTO": "false", "TMUX_AUTO": "false",
"STARTUP_GRACE_SEC": "1", "STARTUP_GRACE_SEC": "1",
"CHECK_INTERVAL": "2", "CHECK_INTERVAL": "2",
"APP_CMD": "sleep 10", "APP_CMD_BIN": "sleep",
"APP_CMD_ARGS": "10",
} }
) )
completed = subprocess.run( completed = subprocess.run(
@@ -137,7 +138,7 @@ def test_run_overnight_fails_when_process_exits_before_grace_period(tmp_path: Pa
"LOG_DIR": str(log_dir), "LOG_DIR": str(log_dir),
"TMUX_AUTO": "false", "TMUX_AUTO": "false",
"STARTUP_GRACE_SEC": "1", "STARTUP_GRACE_SEC": "1",
"APP_CMD": "false", "APP_CMD_BIN": "false",
} }
) )
completed = subprocess.run( completed = subprocess.run(