Add cross-platform setup and start scripts
Use shell-based setup and startup flows that work more reliably across Windows bash environments and Linux. This keeps environment bootstrap and service startup aligned while avoiding fragile process handling. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
204
setup.sh
Normal file
204
setup.sh
Normal file
@@ -0,0 +1,204 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
BACKEND_DIR="$SCRIPT_DIR/backend"
|
||||
FRONTEND_DIR="$SCRIPT_DIR/frontend"
|
||||
ROOT_ENV="$SCRIPT_DIR/.env"
|
||||
BACKEND_ENV="$BACKEND_DIR/.env"
|
||||
BACKEND_ENV_EXAMPLE="$BACKEND_DIR/.env.example"
|
||||
FRONTEND_ENV_LOCAL="$FRONTEND_DIR/.env.local"
|
||||
HOST_OS="$(uname -s)"
|
||||
USE_WINDOWS_TOOLS=false
|
||||
|
||||
if command -v cmd.exe >/dev/null 2>&1 || command -v powershell.exe >/dev/null 2>&1; then
|
||||
USE_WINDOWS_TOOLS=true
|
||||
fi
|
||||
|
||||
if [[ "$USE_WINDOWS_TOOLS" == true ]]; then
|
||||
BACKEND_PYTHON="$BACKEND_DIR/.venv/Scripts/python.exe"
|
||||
FRONTEND_NPM="npm.cmd"
|
||||
else
|
||||
BACKEND_PYTHON="$BACKEND_DIR/.venv/bin/python"
|
||||
FRONTEND_NPM="npm"
|
||||
fi
|
||||
|
||||
print_header() {
|
||||
echo "=========================================="
|
||||
echo " Jarvis - Setup"
|
||||
echo "=========================================="
|
||||
echo
|
||||
}
|
||||
|
||||
require_command() {
|
||||
local command_name="$1"
|
||||
local hint="$2"
|
||||
if ! command -v "$command_name" >/dev/null 2>&1; then
|
||||
echo "[ERROR] $command_name was not found."
|
||||
echo "[ERROR] $hint"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_backend_env() {
|
||||
if [[ -f "$BACKEND_ENV" ]]; then
|
||||
echo "[OK] Backend env file exists: $BACKEND_ENV"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -f "$ROOT_ENV" ]]; then
|
||||
cp "$ROOT_ENV" "$BACKEND_ENV"
|
||||
echo "[INFO] Created backend/.env from root .env"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -f "$BACKEND_ENV_EXAMPLE" ]]; then
|
||||
cp "$BACKEND_ENV_EXAMPLE" "$BACKEND_ENV"
|
||||
echo "[INFO] Created backend/.env from backend/.env.example"
|
||||
echo "[INFO] Edit $BACKEND_ENV before running start.sh if needed."
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "[ERROR] Could not create backend/.env"
|
||||
exit 1
|
||||
}
|
||||
|
||||
sync_frontend_env() {
|
||||
local backend_host
|
||||
local backend_port
|
||||
|
||||
backend_host="$(grep '^HOST=' "$BACKEND_ENV" | cut -d'=' -f2- | tr -d '\r' || true)"
|
||||
backend_port="$(grep '^PORT=' "$BACKEND_ENV" | cut -d'=' -f2- | tr -d '\r' || true)"
|
||||
|
||||
[[ -z "$backend_host" ]] && backend_host="127.0.0.1"
|
||||
[[ -z "$backend_port" ]] && backend_port="3337"
|
||||
|
||||
printf 'VITE_API_URL=http://%s:%s\n' "$backend_host" "$backend_port" > "$FRONTEND_ENV_LOCAL"
|
||||
echo "[OK] Synced frontend/.env.local -> http://$backend_host:$backend_port"
|
||||
}
|
||||
|
||||
print_header
|
||||
|
||||
require_command npm "Install Node.js and npm first."
|
||||
|
||||
if [[ "$USE_WINDOWS_TOOLS" == true ]]; then
|
||||
if command -v py.exe >/dev/null 2>&1; then
|
||||
PYTHON_BOOTSTRAP=("py.exe" "-3")
|
||||
elif command -v python.exe >/dev/null 2>&1; then
|
||||
PYTHON_BOOTSTRAP=("python.exe")
|
||||
elif command -v python >/dev/null 2>&1; then
|
||||
PYTHON_BOOTSTRAP=("python")
|
||||
else
|
||||
echo "[ERROR] Python was not found."
|
||||
echo "[ERROR] Install Python 3.12+ for Windows first."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if command -v python3 >/dev/null 2>&1; then
|
||||
PYTHON_BOOTSTRAP=("python3")
|
||||
elif command -v python >/dev/null 2>&1; then
|
||||
PYTHON_BOOTSTRAP=("python")
|
||||
else
|
||||
echo "[ERROR] python3/python was not found."
|
||||
echo "[ERROR] Install Python 3.12+ first."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
install_backend_dependencies() {
|
||||
if command -v uv >/dev/null 2>&1; then
|
||||
echo "[INFO] Using uv to install backend dependencies..."
|
||||
(
|
||||
cd "$BACKEND_DIR"
|
||||
uv sync
|
||||
)
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "[INFO] uv was not found. Falling back to venv + pip..."
|
||||
(
|
||||
cd "$BACKEND_DIR"
|
||||
if ! "${PYTHON_BOOTSTRAP[@]}" -m venv .venv; then
|
||||
echo "[WARN] python -m venv failed. Trying virtualenv fallback..."
|
||||
"${PYTHON_BOOTSTRAP[@]}" -m pip install --user virtualenv
|
||||
"${PYTHON_BOOTSTRAP[@]}" -m virtualenv .venv
|
||||
fi
|
||||
if [[ "$USE_WINDOWS_TOOLS" == true ]]; then
|
||||
.venv/Scripts/python.exe -m pip install --upgrade pip
|
||||
.venv/Scripts/python.exe -m pip install -e .
|
||||
else
|
||||
.venv/bin/python -m pip install --upgrade pip
|
||||
.venv/bin/python -m pip install -e .
|
||||
fi
|
||||
)
|
||||
}
|
||||
|
||||
install_frontend_dependencies() {
|
||||
if [[ "$USE_WINDOWS_TOOLS" == true ]]; then
|
||||
(
|
||||
cd "$FRONTEND_DIR"
|
||||
if [[ -f "package-lock.json" ]]; then
|
||||
cmd.exe /c npm ci
|
||||
else
|
||||
cmd.exe /c npm install
|
||||
fi
|
||||
)
|
||||
else
|
||||
(
|
||||
cd "$FRONTEND_DIR"
|
||||
if [[ -f "package-lock.json" ]]; then
|
||||
npm ci
|
||||
else
|
||||
npm install
|
||||
fi
|
||||
)
|
||||
fi
|
||||
|
||||
if [[ -f "$FRONTEND_DIR/node_modules/.bin/vite" || -f "$FRONTEND_DIR/node_modules/.bin/vite.cmd" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "[ERROR] Frontend dependencies were installed, but vite was not found."
|
||||
echo "[ERROR] Check frontend/node_modules and npm output."
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "[1/4] Prepare backend environment file..."
|
||||
ensure_backend_env
|
||||
|
||||
echo
|
||||
echo "[2/4] Install backend dependencies..."
|
||||
install_backend_dependencies
|
||||
|
||||
if [[ "$USE_WINDOWS_TOOLS" == true ]]; then
|
||||
if [[ ! -f "$BACKEND_PYTHON" ]]; then
|
||||
echo "[ERROR] Backend virtual environment Python was not found after setup: $BACKEND_PYTHON"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if [[ ! -x "$BACKEND_PYTHON" ]]; then
|
||||
echo "[ERROR] Backend virtual environment Python was not found after setup: $BACKEND_PYTHON"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "[OK] Backend dependencies installed."
|
||||
|
||||
echo
|
||||
echo "[3/4] Install frontend dependencies..."
|
||||
install_frontend_dependencies
|
||||
echo "[OK] Frontend dependencies installed."
|
||||
|
||||
echo
|
||||
echo "[4/4] Sync frontend API configuration..."
|
||||
sync_frontend_env
|
||||
|
||||
echo
|
||||
echo "=========================================="
|
||||
echo " Setup complete"
|
||||
echo
|
||||
echo " Backend env: $BACKEND_ENV"
|
||||
echo " Frontend env: $FRONTEND_ENV_LOCAL"
|
||||
echo
|
||||
echo " Next: bash start.sh"
|
||||
echo "=========================================="
|
||||
277
start.sh
277
start.sh
@@ -5,24 +5,48 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
BACKEND_DIR="$SCRIPT_DIR/backend"
|
||||
FRONTEND_DIR="$SCRIPT_DIR/frontend"
|
||||
LOG_DIR="$SCRIPT_DIR/logs"
|
||||
PROJECT_ENV="$SCRIPT_DIR/.env"
|
||||
ROOT_ENV="$SCRIPT_DIR/.env"
|
||||
BACKEND_ENV="$BACKEND_DIR/.env"
|
||||
BACKEND_ENV_EXAMPLE="$BACKEND_DIR/.env.example"
|
||||
FRONTEND_ENV_LOCAL="$FRONTEND_DIR/.env.local"
|
||||
BACKEND_PYTHON="$BACKEND_DIR/.venv/Scripts/python.exe"
|
||||
FRONTEND_VITE="$FRONTEND_DIR/node_modules/.bin/vite.cmd"
|
||||
HOST_OS="$(uname -s)"
|
||||
USE_WINDOWS_TOOLS=false
|
||||
|
||||
if command -v cmd.exe >/dev/null 2>&1 || command -v powershell.exe >/dev/null 2>&1; then
|
||||
USE_WINDOWS_TOOLS=true
|
||||
fi
|
||||
|
||||
if [[ "$USE_WINDOWS_TOOLS" == true ]]; then
|
||||
BACKEND_PYTHON="$BACKEND_DIR/.venv/Scripts/python.exe"
|
||||
FRONTEND_NPM="npm.cmd"
|
||||
else
|
||||
BACKEND_PYTHON="$BACKEND_DIR/.venv/bin/python"
|
||||
FRONTEND_NPM="npm"
|
||||
fi
|
||||
|
||||
RUN_ID="$(date +%Y%m%d-%H%M%S)"
|
||||
BACKEND_LOG="$LOG_DIR/backend-start-${RUN_ID}.log"
|
||||
BACKEND_ERR_LOG="$LOG_DIR/backend-start-${RUN_ID}.err.log"
|
||||
FRONTEND_LOG="$LOG_DIR/frontend-start-${RUN_ID}.log"
|
||||
FRONTEND_ERR_LOG="$LOG_DIR/frontend-start-${RUN_ID}.err.log"
|
||||
KILL_PORT=false
|
||||
ENABLE_RELOAD=false
|
||||
|
||||
if [[ "${1:-}" == "--kill-port" ]]; then
|
||||
KILL_PORT=true
|
||||
elif [[ $# -gt 0 ]]; then
|
||||
echo "[ERROR] Unsupported argument: $1"
|
||||
echo "[ERROR] Usage: bash start.sh [--kill-port]"
|
||||
exit 1
|
||||
fi
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--kill-port)
|
||||
KILL_PORT=true
|
||||
;;
|
||||
--reload)
|
||||
ENABLE_RELOAD=true
|
||||
;;
|
||||
*)
|
||||
echo "[ERROR] Unsupported argument: $arg"
|
||||
echo "[ERROR] Usage: bash start.sh [--kill-port] [--reload]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
mkdir -p "$LOG_DIR"
|
||||
|
||||
@@ -40,6 +64,8 @@ to_windows_path() {
|
||||
local path="$1"
|
||||
if [[ "$path" =~ ^/mnt/([a-zA-Z])/(.*)$ ]]; then
|
||||
printf '%s:/%s' "${BASH_REMATCH[1]^}" "${BASH_REMATCH[2]}"
|
||||
elif [[ "$path" =~ ^/cygdrive/([a-zA-Z])/(.*)$ ]]; then
|
||||
printf '%s:/%s' "${BASH_REMATCH[1]^}" "${BASH_REMATCH[2]}"
|
||||
elif [[ "$path" =~ ^/([a-zA-Z])/(.*)$ ]]; then
|
||||
printf '%s:/%s' "${BASH_REMATCH[1]^}" "${BASH_REMATCH[2]}"
|
||||
else
|
||||
@@ -47,13 +73,74 @@ to_windows_path() {
|
||||
fi
|
||||
}
|
||||
|
||||
quote_ps() {
|
||||
local value="$1"
|
||||
value="$(printf '%s' "$value" | sed "s/'/''/g")"
|
||||
printf '%s' "$value"
|
||||
}
|
||||
|
||||
sync_backend_env() {
|
||||
if [[ -f "$BACKEND_ENV" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -f "$ROOT_ENV" ]]; then
|
||||
cp "$ROOT_ENV" "$BACKEND_ENV"
|
||||
echo "[INFO] Created backend/.env from root .env"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -f "$BACKEND_ENV_EXAMPLE" ]]; then
|
||||
cp "$BACKEND_ENV_EXAMPLE" "$BACKEND_ENV"
|
||||
echo "[INFO] Created backend/.env from backend/.env.example"
|
||||
echo "[INFO] Review $BACKEND_ENV before first run."
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "[ERROR] backend/.env was not found and could not be initialized."
|
||||
echo "[ERROR] Run: bash setup.sh"
|
||||
exit 1
|
||||
}
|
||||
|
||||
read_env_value() {
|
||||
local key="$1"
|
||||
local file="$2"
|
||||
grep "^${key}=" "$file" | cut -d'=' -f2- | tr -d '\r' || true
|
||||
}
|
||||
|
||||
write_frontend_env() {
|
||||
local backend_host="$1"
|
||||
local backend_port="$2"
|
||||
printf 'VITE_API_URL=http://%s:%s\n' "$backend_host" "$backend_port" > "$FRONTEND_ENV_LOCAL"
|
||||
}
|
||||
|
||||
kill_port_process() {
|
||||
local port="$1"
|
||||
|
||||
if [[ "$USE_WINDOWS_TOOLS" == true ]]; then
|
||||
local pids
|
||||
pids="$(powershell.exe -NoProfile -Command "Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue | Select-Object -ExpandProperty OwningProcess -Unique" | tr -d '\r' || true)"
|
||||
|
||||
if [[ -z "$pids" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
while IFS= read -r pid; do
|
||||
[[ -z "$pid" ]] && continue
|
||||
cmd.exe /c "taskkill /PID $pid /T /F" >/dev/null 2>&1 || true
|
||||
powershell.exe -NoProfile -Command "Stop-Process -Id $pid -Force -ErrorAction SilentlyContinue" >/dev/null 2>&1 || true
|
||||
done <<< "$pids"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local pids
|
||||
pids="$(powershell.exe -NoProfile -Command '& {
|
||||
Get-NetTCPConnection -LocalPort '"$1"' -State Listen -ErrorAction SilentlyContinue |
|
||||
Select-Object -ExpandProperty OwningProcess -Unique
|
||||
}' | tr -d '\r' || true)"
|
||||
if command -v ss >/dev/null 2>&1; then
|
||||
pids="$(ss -ltnp "sport = :$port" 2>/dev/null | sed -n 's/.*pid=\([0-9]\+\).*/\1/p' | sort -u || true)"
|
||||
elif command -v lsof >/dev/null 2>&1; then
|
||||
pids="$(lsof -ti tcp:"$port" 2>/dev/null | sort -u || true)"
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -z "$pids" ]]; then
|
||||
return 0
|
||||
@@ -61,15 +148,14 @@ kill_port_process() {
|
||||
|
||||
while IFS= read -r pid; do
|
||||
[[ -z "$pid" ]] && continue
|
||||
powershell.exe -NoProfile -Command "Stop-Process -Id $pid -Force -ErrorAction SilentlyContinue" >/dev/null 2>&1 || true
|
||||
cmd.exe /c "taskkill /PID $pid /F" >/dev/null 2>&1 || true
|
||||
kill "$pid" >/dev/null 2>&1 || true
|
||||
done <<< "$pids"
|
||||
}
|
||||
|
||||
kill_process_tree() {
|
||||
local pid="$1"
|
||||
[[ -z "$pid" ]] && return 0
|
||||
cmd.exe /c "taskkill /PID $pid /T /F" >/dev/null 2>&1 || true
|
||||
kill "$pid" >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
@@ -81,72 +167,84 @@ cleanup() {
|
||||
if [[ -n "${BACKEND_PID:-}" ]]; then
|
||||
kill_process_tree "$BACKEND_PID"
|
||||
fi
|
||||
if [[ -n "${BACKEND_PORT:-}" ]]; then
|
||||
kill_port_process "$BACKEND_PORT"
|
||||
fi
|
||||
exit "$exit_code"
|
||||
}
|
||||
trap cleanup INT TERM EXIT
|
||||
|
||||
echo "=========================================="
|
||||
echo " Jarvis - Quick Start"
|
||||
echo " Jarvis - Start"
|
||||
echo "=========================================="
|
||||
echo
|
||||
|
||||
if [[ ! -x "$BACKEND_PYTHON" ]]; then
|
||||
echo "[ERROR] backend/.venv/Scripts/python.exe was not found."
|
||||
echo "[ERROR] Create the backend virtual environment first."
|
||||
sync_backend_env
|
||||
|
||||
if [[ ! -f "$BACKEND_ENV" ]]; then
|
||||
echo "[ERROR] Backend env file was not found: $BACKEND_ENV"
|
||||
echo "[ERROR] Run: bash setup.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$FRONTEND_VITE" ]]; then
|
||||
echo "[ERROR] frontend/node_modules/.bin/vite.cmd was not found."
|
||||
echo "[ERROR] Install frontend dependencies first."
|
||||
exit 1
|
||||
if [[ "$USE_WINDOWS_TOOLS" == true ]]; then
|
||||
if [[ ! -f "$BACKEND_PYTHON" ]]; then
|
||||
echo "[ERROR] Backend virtual environment Python was not found: $BACKEND_PYTHON"
|
||||
echo "[ERROR] Run: bash setup.sh"
|
||||
exit 1
|
||||
fi
|
||||
if ! command -v "$FRONTEND_NPM" >/dev/null 2>&1; then
|
||||
echo "[ERROR] npm.cmd was not found."
|
||||
echo "[ERROR] Install Node.js and ensure npm is on PATH."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if [[ ! -x "$BACKEND_PYTHON" ]]; then
|
||||
echo "[ERROR] Backend virtual environment Python was not found: $BACKEND_PYTHON"
|
||||
echo "[ERROR] Run: bash setup.sh"
|
||||
exit 1
|
||||
fi
|
||||
if ! command -v "$FRONTEND_NPM" >/dev/null 2>&1; then
|
||||
echo "[ERROR] npm was not found."
|
||||
echo "[ERROR] Install Node.js and ensure npm is on PATH."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! command -v powershell.exe >/dev/null 2>&1; then
|
||||
if [[ "$USE_WINDOWS_TOOLS" == true ]] && ! command -v powershell.exe >/dev/null 2>&1; then
|
||||
echo "[ERROR] powershell.exe was not found."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$PROJECT_ENV" ]]; then
|
||||
echo "[INFO] .env was not found in the project root."
|
||||
echo "[INFO] Create it before first run."
|
||||
echo
|
||||
fi
|
||||
BACKEND_HOST="$(read_env_value HOST "$BACKEND_ENV")"
|
||||
BACKEND_PORT="$(read_env_value PORT "$BACKEND_ENV")"
|
||||
|
||||
echo "[1/3] Check backend environment..."
|
||||
echo "[OK] Backend virtual environment is available."
|
||||
|
||||
echo
|
||||
echo "[2/3] Check frontend dependencies..."
|
||||
if [[ ! -x "$FRONTEND_DIR/node_modules/.bin/vite" && ! -x "$FRONTEND_DIR/node_modules/.bin/vite.cmd" ]]; then
|
||||
echo "[ERROR] frontend dependencies are missing."
|
||||
echo "[ERROR] Run: cd frontend && npm install"
|
||||
exit 1
|
||||
fi
|
||||
echo "[OK] Frontend dependencies are available."
|
||||
|
||||
BACKEND_HOST="127.0.0.1"
|
||||
BACKEND_PORT=""
|
||||
if [[ -f "$PROJECT_ENV" ]]; then
|
||||
ENV_HOST="$(grep '^HOST=' "$PROJECT_ENV" | cut -d'=' -f2- | tr -d '\r' || true)"
|
||||
ENV_PORT="$(grep '^PORT=' "$PROJECT_ENV" | cut -d'=' -f2- | tr -d '\r' || true)"
|
||||
if [[ -n "$ENV_HOST" ]]; then BACKEND_HOST="$ENV_HOST"; fi
|
||||
if [[ -n "$ENV_PORT" ]]; then BACKEND_PORT="$ENV_PORT"; fi
|
||||
fi
|
||||
[[ -z "$BACKEND_HOST" ]] && BACKEND_HOST="127.0.0.1"
|
||||
|
||||
if [[ -z "$BACKEND_PORT" ]]; then
|
||||
echo "[ERROR] PORT was not found in .env."
|
||||
echo "[ERROR] Set PORT in the project root .env and run start.sh again."
|
||||
echo "[ERROR] PORT was not found in $BACKEND_ENV"
|
||||
echo "[ERROR] Set PORT and run start.sh again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
FRONTEND_API_URL="http://${BACKEND_HOST}:${BACKEND_PORT}"
|
||||
printf 'VITE_API_URL=%s\n' "$FRONTEND_API_URL" > "$FRONTEND_ENV_LOCAL"
|
||||
if ! [[ "$BACKEND_PORT" =~ ^[0-9]+$ ]]; then
|
||||
echo "[ERROR] PORT must be numeric in $BACKEND_ENV: $BACKEND_PORT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if (( BACKEND_PORT < 1 || BACKEND_PORT > 65535 )); then
|
||||
echo "[ERROR] PORT must be between 1 and 65535 in $BACKEND_ENV: $BACKEND_PORT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
write_frontend_env "$BACKEND_HOST" "$BACKEND_PORT"
|
||||
|
||||
BACKEND_ARGS=(-m uvicorn app.main:app --host "$BACKEND_HOST" --port "$BACKEND_PORT")
|
||||
if [[ "$ENABLE_RELOAD" == true ]]; then
|
||||
BACKEND_ARGS+=(--reload)
|
||||
fi
|
||||
|
||||
echo "[1/3] Backend environment ready."
|
||||
echo "[2/3] Frontend environment ready."
|
||||
echo
|
||||
|
||||
echo "[3/3] Start services..."
|
||||
if port_in_use "$BACKEND_PORT"; then
|
||||
if [[ "$KILL_PORT" == true ]]; then
|
||||
@@ -158,67 +256,72 @@ fi
|
||||
|
||||
if port_in_use "$BACKEND_PORT"; then
|
||||
echo "[ERROR] Port ${BACKEND_PORT} is already in use."
|
||||
echo "[ERROR] Stop the existing service first, then run start.sh again."
|
||||
echo "[ERROR] Stop the existing service first, or run: bash start.sh --kill-port"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BACKEND_WIN_DIR="$(to_windows_path "$BACKEND_DIR")"
|
||||
BACKEND_WIN_LOG="$(to_windows_path "$BACKEND_LOG")"
|
||||
BACKEND_WIN_ERR_LOG="$(to_windows_path "$BACKEND_ERR_LOG")"
|
||||
BACKEND_WIN_PYTHON="$(to_windows_path "$BACKEND_PYTHON")"
|
||||
BACKEND_PID="$(powershell.exe -NoProfile -Command "& {
|
||||
\$process = Start-Process -FilePath '$BACKEND_WIN_PYTHON' -ArgumentList '-m','uvicorn','app.main:app','--reload','--host','$BACKEND_HOST','--port','$BACKEND_PORT' -WorkingDirectory '$BACKEND_WIN_DIR' -RedirectStandardOutput '$BACKEND_WIN_LOG' -RedirectStandardError '$BACKEND_WIN_ERR_LOG' -PassThru
|
||||
\$process.Id
|
||||
}" | tr -d '\r')"
|
||||
(
|
||||
cd "$BACKEND_DIR"
|
||||
exec "$BACKEND_PYTHON" "${BACKEND_ARGS[@]}"
|
||||
) >"$BACKEND_LOG" 2>"$BACKEND_ERR_LOG" &
|
||||
BACKEND_PID="$!"
|
||||
|
||||
echo "Waiting for backend..."
|
||||
sleep 5
|
||||
|
||||
if ! port_in_use "$BACKEND_PORT"; then
|
||||
echo "[ERROR] Backend did not start successfully."
|
||||
echo "[ERROR] Check log: $BACKEND_LOG"
|
||||
echo "[ERROR] Check logs: $BACKEND_LOG $BACKEND_ERR_LOG"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Starting frontend on port 5173..."
|
||||
FRONTEND_WIN_DIR="$(to_windows_path "$FRONTEND_DIR")"
|
||||
FRONTEND_WIN_LOG="$(to_windows_path "$FRONTEND_LOG")"
|
||||
FRONTEND_WIN_ERR_LOG="$(to_windows_path "$FRONTEND_ERR_LOG")"
|
||||
FRONTEND_WIN_VITE="$(to_windows_path "$FRONTEND_VITE")"
|
||||
FRONTEND_PID="$(powershell.exe -NoProfile -Command "& {
|
||||
\$process = Start-Process -FilePath '$FRONTEND_WIN_VITE' -ArgumentList '--host','0.0.0.0' -WorkingDirectory '$FRONTEND_WIN_DIR' -RedirectStandardOutput '$FRONTEND_WIN_LOG' -RedirectStandardError '$FRONTEND_WIN_ERR_LOG' -PassThru
|
||||
\$process.Id
|
||||
}" | tr -d '\r')"
|
||||
FRONTEND_HOST="0.0.0.0"
|
||||
FRONTEND_BROWSER_HOST="localhost"
|
||||
FRONTEND_PORT="5173"
|
||||
|
||||
echo "Starting frontend on port ${FRONTEND_PORT}..."
|
||||
if [[ "$USE_WINDOWS_TOOLS" == true ]]; then
|
||||
(
|
||||
cd "$FRONTEND_DIR"
|
||||
exec cmd.exe /c npm run dev -- --host "$FRONTEND_HOST"
|
||||
) >"$FRONTEND_LOG" 2>"$FRONTEND_ERR_LOG" &
|
||||
FRONTEND_PID="$!"
|
||||
else
|
||||
(
|
||||
cd "$FRONTEND_DIR"
|
||||
exec "$FRONTEND_NPM" run dev -- --host "$FRONTEND_HOST"
|
||||
) >"$FRONTEND_LOG" 2>"$FRONTEND_ERR_LOG" &
|
||||
FRONTEND_PID="$!"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "=========================================="
|
||||
echo " Started"
|
||||
echo
|
||||
echo " Backend: http://${BACKEND_HOST}:${BACKEND_PORT}"
|
||||
echo " Frontend: http://localhost:5173"
|
||||
echo " API docs: http://${BACKEND_HOST}:${BACKEND_PORT}/docs"
|
||||
echo " Backend: http://${BACKEND_HOST}:${BACKEND_PORT}"
|
||||
echo " Frontend: http://${FRONTEND_BROWSER_HOST}:${FRONTEND_PORT}"
|
||||
echo " API docs: http://${BACKEND_HOST}:${BACKEND_PORT}/docs"
|
||||
echo
|
||||
echo " Logs:"
|
||||
echo " - $BACKEND_LOG"
|
||||
echo " - $BACKEND_ERR_LOG"
|
||||
echo " - $FRONTEND_LOG"
|
||||
echo " - $FRONTEND_ERR_LOG"
|
||||
echo "=========================================="
|
||||
echo
|
||||
echo "Press Ctrl+C to stop both services."
|
||||
echo
|
||||
|
||||
while true; do
|
||||
backend_alive="$(powershell.exe -NoProfile -Command "Get-Process -Id $BACKEND_PID -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Id" | tr -d '\r')"
|
||||
frontend_alive="$(powershell.exe -NoProfile -Command "Get-Process -Id $FRONTEND_PID -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Id" | tr -d '\r')"
|
||||
|
||||
if [[ -z "$backend_alive" ]]; then
|
||||
if ! kill -0 "$BACKEND_PID" >/dev/null 2>&1; then
|
||||
echo "[ERROR] Backend process exited."
|
||||
echo "[ERROR] Check log: $BACKEND_LOG"
|
||||
echo "[ERROR] Check logs: $BACKEND_LOG $BACKEND_ERR_LOG"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "$frontend_alive" ]]; then
|
||||
if ! kill -0 "$FRONTEND_PID" >/dev/null 2>&1; then
|
||||
echo "[ERROR] Frontend process exited."
|
||||
echo "[ERROR] Check log: $FRONTEND_LOG"
|
||||
echo "[ERROR] Check logs: $FRONTEND_LOG $FRONTEND_ERR_LOG"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user