131 lines
4.0 KiB
Bash
131 lines
4.0 KiB
Bash
#!/usr/bin/env bash
|
|
# Deploy backend: build release, stop running process gracefully (PID file & pgrep fallback), rotate logs, and start via nohup
|
|
# Usage:
|
|
# ENV_FILE=prod ./scripts/deploy_backend.sh
|
|
# ENV_FILE=staging ./scripts/deploy_backend.sh
|
|
# Notes:
|
|
# - ENV_FILE will be exported for the backend to decide which .env to load (e.g., .env.prod).
|
|
# - PID is stored in backend/udmin.pid.
|
|
|
|
set -euo pipefail
|
|
|
|
# 获取脚本所在目录的绝对路径
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
BACKEND_DIR="$ROOT_DIR/backend"
|
|
BIN_PATH="$BACKEND_DIR/target/release/udmin"
|
|
LOG_FILE="$BACKEND_DIR/udmin.log"
|
|
PID_FILE="$BACKEND_DIR/udmin.pid"
|
|
ENV_FILE_VALUE="${ENV_FILE:-prod}"
|
|
|
|
# 调试信息:打印关键路径
|
|
echo "[backend] Script directory: $SCRIPT_DIR"
|
|
echo "[backend] Root directory: $ROOT_DIR"
|
|
echo "[backend] Backend directory: $BACKEND_DIR"
|
|
echo "[backend] Binary path: $BIN_PATH"
|
|
|
|
# 检查关键目录是否存在
|
|
if [ ! -d "$BACKEND_DIR" ]; then
|
|
echo "[backend] ERROR: Backend directory does not exist: $BACKEND_DIR" >&2
|
|
echo "[backend] Please ensure the script is placed in the correct location relative to the project structure" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -f "$BACKEND_DIR/Cargo.toml" ]; then
|
|
echo "[backend] ERROR: Cargo.toml not found in backend directory: $BACKEND_DIR" >&2
|
|
echo "[backend] This doesn't appear to be a valid Rust project directory" >&2
|
|
exit 1
|
|
fi
|
|
|
|
cd "$BACKEND_DIR"
|
|
|
|
echo "[backend] Building release binary..."
|
|
cargo build --release
|
|
|
|
if [ ! -x "$BIN_PATH" ]; then
|
|
echo "[backend] ERROR: Binary not found or not executable: $BIN_PATH" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Gracefully stop existing process (PID file first)
|
|
stop_pid() {
|
|
local pid="$1"
|
|
if [ -z "$pid" ]; then return 0; fi
|
|
if ! ps -p "$pid" >/dev/null 2>&1; then return 0; fi
|
|
echo "[backend] Stopping udmin (pid=$pid) ..."
|
|
kill -TERM "$pid" || true
|
|
for i in {1..10}; do
|
|
if ps -p "$pid" >/dev/null 2>&1; then
|
|
sleep 1
|
|
else
|
|
break
|
|
fi
|
|
done
|
|
if ps -p "$pid" >/dev/null 2>&1; then
|
|
echo "[backend] Force killing udmin (pid=$pid) ..."
|
|
kill -KILL "$pid" || true
|
|
fi
|
|
}
|
|
|
|
# 1) Stop by PID file if present
|
|
echo "[backend] Checking for existing PID file: $PID_FILE"
|
|
if [ -f "$PID_FILE" ]; then
|
|
PID_CONTENT="$(cat "$PID_FILE" 2>/dev/null || true)"
|
|
if [ -n "$PID_CONTENT" ]; then
|
|
echo "[backend] Found PID file with PID: $PID_CONTENT"
|
|
stop_pid "$PID_CONTENT"
|
|
else
|
|
echo "[backend] PID file exists but is empty"
|
|
fi
|
|
rm -f "$PID_FILE"
|
|
echo "[backend] Removed PID file"
|
|
else
|
|
echo "[backend] No PID file found"
|
|
fi
|
|
|
|
# 2) Fallback: stop any process matching the release binary path (safe, avoids killing debug run)
|
|
echo "[backend] Searching for existing processes matching: $BIN_PATH"
|
|
PGREP_PIDS="$(pgrep -f "$BIN_PATH" 2>/dev/null || true)"
|
|
if [ -n "$PGREP_PIDS" ]; then
|
|
echo "[backend] Found existing udmin processes by path: $PGREP_PIDS"
|
|
for p in $PGREP_PIDS; do
|
|
echo "[backend] Stopping process: $p"
|
|
stop_pid "$p"
|
|
done
|
|
else
|
|
echo "[backend] No existing processes found matching the binary path"
|
|
fi
|
|
|
|
# Rotate log
|
|
TS="$(date +%Y%m%d%H%M%S)"
|
|
if [ -f "$LOG_FILE" ]; then
|
|
mv "$LOG_FILE" "$LOG_FILE.$TS" || true
|
|
fi
|
|
|
|
echo "[backend] Starting udmin (ENV_FILE=$ENV_FILE_VALUE) ..."
|
|
export ENV_FILE="$ENV_FILE_VALUE"
|
|
nohup "$BIN_PATH" > "$LOG_FILE" 2>&1 &
|
|
NEW_PID=$!
|
|
|
|
echo "$NEW_PID" > "$PID_FILE"
|
|
|
|
echo "[backend] Started with PID: $NEW_PID"
|
|
echo "[backend] Logs: $LOG_FILE"
|
|
echo "[backend] PID file: $PID_FILE"
|
|
|
|
# 等待几秒钟验证进程是否成功启动
|
|
echo "[backend] Waiting 3 seconds to verify startup..."
|
|
sleep 3
|
|
|
|
if ps -p "$NEW_PID" > /dev/null 2>&1; then
|
|
echo "[backend] ✅ Process is running successfully (PID: $NEW_PID)"
|
|
echo "[backend] Deployment completed successfully!"
|
|
else
|
|
echo "[backend] ❌ ERROR: Process failed to start or crashed immediately" >&2
|
|
echo "[backend] Check the log file for details: $LOG_FILE" >&2
|
|
if [ -f "$LOG_FILE" ]; then
|
|
echo "[backend] Last few lines of log:" >&2
|
|
tail -10 "$LOG_FILE" >&2
|
|
fi
|
|
exit 1
|
|
fi |