#!/usr/bin/env sh set -eu PROJECT_DIR="/opt/people-flow" CONFIG_TEMPLATE="${PROJECT_DIR}/config/config.example.yaml" CONFIG_PATH="${CONFIG_PATH:-${PROJECT_DIR}/config/local.yaml}" OUTPUT_DIR="${OUTPUT_DIR:-${PROJECT_DIR}/outputs}" RTSP_URL="${RTSP_URL:-}" API_HOST="${API_HOST:-0.0.0.0}" API_PORT="${API_PORT:-18082}" mkdir -p "${OUTPUT_DIR}" "$(dirname "${CONFIG_PATH}")" if [ ! -f "${CONFIG_PATH}" ]; then cp "${CONFIG_TEMPLATE}" "${CONFIG_PATH}" fi python - "$CONFIG_PATH" "$RTSP_URL" "$OUTPUT_DIR" <<'PY' from pathlib import Path import sys import yaml config_path = Path(sys.argv[1]) rtsp_url = sys.argv[2] output_dir = sys.argv[3] raw = yaml.safe_load(config_path.read_text(encoding="utf-8")) or {} runtime = raw.setdefault("runtime", {}) if rtsp_url: runtime["rtsp_url"] = rtsp_url runtime["output_dir"] = output_dir yolo = raw.setdefault("yolo", {}) yolo.setdefault("model_path", "weights/yolo11n.pt") config_path.write_text( yaml.safe_dump(raw, allow_unicode=True, sort_keys=False), encoding="utf-8", ) PY exec python - "$CONFIG_PATH" "$API_HOST" "$API_PORT" <<'PY' import signal import subprocess import sys import time config_path, api_host, api_port = sys.argv[1:4] commands = [ [sys.executable, "main.py", "--config", config_path, "rtsp"], [ sys.executable, "main.py", "--config", config_path, "manage-api", "--host", api_host, "--port", api_port, ], ] processes = [subprocess.Popen(command) for command in commands] def terminate_all(signum, _frame): for process in processes: if process.poll() is None: process.terminate() deadline = time.time() + 10 for process in processes: if process.poll() is not None: continue timeout = max(0, deadline - time.time()) try: process.wait(timeout=timeout) except subprocess.TimeoutExpired: process.kill() raise SystemExit(128 + signum) for handled_signal in (signal.SIGINT, signal.SIGTERM): signal.signal(handled_signal, terminate_all) while True: for index, process in enumerate(processes): return_code = process.poll() if return_code is None: continue for other_index, other_process in enumerate(processes): if other_index == index or other_process.poll() is not None: continue other_process.terminate() deadline = time.time() + 10 for other_index, other_process in enumerate(processes): if other_index == index or other_process.poll() is not None: continue timeout = max(0, deadline - time.time()) try: other_process.wait(timeout=timeout) except subprocess.TimeoutExpired: other_process.kill() raise SystemExit(return_code) time.sleep(0.5) PY