Files
soul-yongping/soul-api/deploy/runner/deploy.sh
Alex-larget 6df1736e1e 1
2026-03-20 14:47:37 +08:00

114 lines
3.2 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# soul-api Runner 容器内红蓝切换脚本
# 用法: /app/deploy.sh /tmp/incoming.tar.gz
# 将新版本解压到非活跃目录,健康检查通过后切换 nginx 并停旧实例
set -e
INCOMING="${1:-}"
APP_ROOT="/app"
BLUE="$APP_ROOT/blue"
GREEN="$APP_ROOT/green"
ACTIVE_FILE="$APP_ROOT/.active"
NGINX_CONF="$APP_ROOT/nginx.conf"
NGINX_PID="/tmp/nginx.pid"
REDIS_PASS="soul-docker-redis"
health_ok() {
local url="$1"
if command -v wget >/dev/null 2>&1; then
wget -qO- "$url" >/dev/null 2>&1
else
[ -x /usr/bin/wget ] && /usr/bin/wget -qO- "$url" >/dev/null 2>&1
fi
}
if [ -z "$INCOMING" ] || [ ! -f "$INCOMING" ]; then
echo "[ERROR] 用法: $0 <path-to-deploy.tar.gz>"
exit 1
fi
# 确定当前活跃与待部署目录
CURRENT="blue"
[ -f "$ACTIVE_FILE" ] && CURRENT=$(cat "$ACTIVE_FILE")
[ "$CURRENT" != "blue" ] && [ "$CURRENT" != "green" ] && CURRENT="blue"
if [ "$CURRENT" = "blue" ]; then
NEW="green"
NEW_PORT=18082
OLD_PORT=18081
else
NEW="blue"
NEW_PORT=18081
OLD_PORT=18082
fi
NEW_DIR="$APP_ROOT/$NEW"
echo "[1/5] 当前活跃: $CURRENT ($OLD_PORT),将部署到: $NEW ($NEW_PORT)"
# 解压到新目录
echo "[2/5] 解压到 $NEW_DIR ..."
rm -rf "$NEW_DIR"
mkdir -p "$NEW_DIR"
tar -xzf "$INCOMING" -C "$NEW_DIR"
rm -f "$INCOMING"
# 设置 PORT 和 REDIS_URL
ENV_FILE="$NEW_DIR/.env"
if [ -f "$ENV_FILE" ]; then
sed -i "s/^PORT=.*/PORT=$NEW_PORT/" "$ENV_FILE"
grep -q "^REDIS_URL=" "$ENV_FILE" || echo "REDIS_URL=redis://:${REDIS_PASS}@127.0.0.1:6379/0" >> "$ENV_FILE"
sed -i "s|^REDIS_URL=.*|REDIS_URL=redis://:${REDIS_PASS}@127.0.0.1:6379/0|" "$ENV_FILE"
fi
chmod +x "$NEW_DIR/soul-api" 2>/dev/null || true
# 启动新实例
echo "[3/5] 启动 soul-api-$NEW (端口 $NEW_PORT) ..."
cd "$NEW_DIR"
export PORT=$NEW_PORT
export REDIS_URL="redis://:${REDIS_PASS}@127.0.0.1:6379/0"
nohup ./soul-api >> soul-api.log 2>&1 &
NEW_PID=$!
echo $NEW_PID > "$APP_ROOT/.pid.$NEW"
cd - >/dev/null
# 等待健康检查(最多 120 秒)
echo "[4/5] 等待健康检查 ..."
sleep 5
for i in $(seq 1 58); do
if health_ok "http://127.0.0.1:$NEW_PORT/health"; then
echo " 健康检查通过"
break
fi
sleep 2
if [ $i -eq 58 ]; then
echo "[ERROR] 健康检查超时,新实例未就绪"
kill $NEW_PID 2>/dev/null || true
exit 1
fi
done
# 更新 nginx 配置并重载
echo "[5/5] 切换 nginx 到 $NEW_PORT ..."
sed "s/__BACKEND_PORT__/$NEW_PORT/g" "$APP_ROOT/nginx.conf.template" > "$NGINX_CONF"
nginx -s reload 2>/dev/null || nginx -c "$NGINX_CONF" 2>/dev/null || true
# 停止旧实例(通过 PID 文件或端口)
OLD_PID_FILE="$APP_ROOT/.pid.$CURRENT"
if [ -f "$OLD_PID_FILE" ]; then
OLD_PID=$(cat "$OLD_PID_FILE")
if kill -0 "$OLD_PID" 2>/dev/null; then
echo " 停止旧实例 (PID $OLD_PID)"
kill "$OLD_PID" 2>/dev/null || true
sleep 2
fi
rm -f "$OLD_PID_FILE"
fi
# 兜底通过端口杀进程Alpine 可用 fuser 或 ss
if command -v fuser >/dev/null 2>&1; then
fuser -k "$OLD_PORT/tcp" 2>/dev/null || true
fi
echo "$NEW" > "$ACTIVE_FILE"
echo ""
echo "[SUCCESS] 部署完成,当前活跃: $NEW (端口 $NEW_PORT)"