fix(update): recover stopped active services

这个提交包含在:
徐勤民 2026-07-29 00:27:49 +08:00
父节点 4d595edcae
当前提交 465910caa0
共有 2 个文件被更改,包括 49 次插入16 次删除

查看文件

@ -543,9 +543,12 @@ _COMPOSE="docker compose --env-file ${ROOT_DIR}/.env \
# 使用 up -d 而非 restartrestart 只重启容器进程,不会切换到新拉取的镜像;
# up -d 会检测镜像变更并重建容器,是应用新版本的正确方式。
# 必须依据当前 profile 是否启用服务,而不能依据服务此刻是否正在运行。升级中断、
# 宿主重启或旧容器启动失败时,后者会永久跳过本应恢复的核心服务。
_active_services="$($_COMPOSE config --services 2>/dev/null || true)"
for _svc in tenant-service im-service file-service update-service push-service tenant-web nginx; do
# 仅重启已激活的服务(跳过未运行的可选服务)
if $_COMPOSE ps --services --filter status=running 2>/dev/null | grep -q "^${_svc}$"; then
# 仅启动当前 profile 已激活的服务;服务即使当前停止也必须被恢复。
if printf '%s\n' "$_active_services" | grep -q "^${_svc}$"; then
info "应用新镜像并重启 ${_svc} ..."
$_COMPOSE up -d --no-deps --remove-orphans "$_svc"
ok "${_svc} 已更新"

查看文件

@ -63,6 +63,31 @@ BASE_URL="${BASE_URL%/}"
MYSQL_PASSWORD="${MYSQL_PASSWORD:-}"
REDIS_PASSWORD="${REDIS_PASSWORD:-}"
# 所有容器定位均限定在当前 Compose 项目。宿主机可能同时运行其他 MySQL、
# Redis 或 Xuqm 环境,按名称模糊匹配会误检、误执行数据库命令。
compose() {
docker compose --env-file "$ROOT_DIR/.env" \
-f "$ROOT_DIR/docker-compose.yml" \
-f "$ROOT_DIR/docker-compose.infra.yml" "$@"
}
container_id() {
compose ps -q "$1" 2>/dev/null | head -1 || true
}
container_name() {
local id
id="$(container_id "$1")"
[ -n "$id" ] && docker inspect --format '{{.Name}}' "$id" 2>/dev/null | sed 's|^/||'
}
profile_enabled() {
case ",${COMPOSE_PROFILES:-base}," in
*,"$1",*) return 0 ;;
*) return 1 ;;
esac
}
# ---------------------------------------------------------------------------
# 颜色和工具函数
# ---------------------------------------------------------------------------
@ -146,23 +171,27 @@ printf " 验证时间: %s\n" "$(date '+%Y-%m-%d %H:%M:%S')"
# ---------------------------------------------------------------------------
section "1. 容器状态"
REQUIRED_CONTAINERS="tenant-service nginx tenant-web"
REQUIRED_CONTAINERS="tenant-service file-service nginx tenant-web"
for CTR_SUFFIX in $REQUIRED_CONTAINERS; do
CTR_NAME=$(docker ps --filter "name=$CTR_SUFFIX" --filter "status=running" --format '{{.Names}}' 2>/dev/null | head -1)
CTR_NAME="$(container_name "$CTR_SUFFIX")"
if [ -n "$CTR_NAME" ]; then
pass "容器运行中: $CTR_NAME"
else
fail "容器未运行: *-${CTR_SUFFIX}-*"
fail "当前部署容器未运行: $CTR_SUFFIX"
fi
done
OPTIONAL_CONTAINERS="file-service im-service push-service update-service bugcollect-service symbolicator mysql redis"
for CTR_SUFFIX in $OPTIONAL_CONTAINERS; do
CTR_NAME=$(docker ps --filter "name=$CTR_SUFFIX" --filter "status=running" --format '{{.Names}}' 2>/dev/null | head -1)
OPTIONAL_SERVICES="im:im-service push:push-service update:update-service bugcollect:bugcollect-service bugcollect:symbolicator infra-mysql:mysql infra-redis:redis"
for PROFILE_SERVICE in $OPTIONAL_SERVICES; do
PROFILE="${PROFILE_SERVICE%%:*}"
CTR_SUFFIX="${PROFILE_SERVICE#*:}"
CTR_NAME="$(container_name "$CTR_SUFFIX")"
if [ -n "$CTR_NAME" ]; then
pass "容器运行中: $CTR_NAME"
elif profile_enabled "$PROFILE"; then
fail "已启用 profile 的容器未运行: $CTR_SUFFIX"
else
warn "容器未运行(可选): *-${CTR_SUFFIX}-*"
warn "容器未启用profile: $PROFILE: $CTR_SUFFIX"
fi
done
@ -172,19 +201,20 @@ done
section "2. 数据库和缓存"
# MySQL
MYSQL_CTR=$(docker ps --filter "name=mysql" --filter "status=running" --format '{{.Names}}' 2>/dev/null | head -1)
MYSQL_CTR="$(container_id mysql)"
if [ -n "$MYSQL_CTR" ]; then
if docker exec "$MYSQL_CTR" mysqladmin -u root -p"${MYSQL_ROOT_PASSWORD:-}" ping --silent 2>/dev/null; then
pass "MySQL 响应 PONG"
if docker exec "$MYSQL_CTR" mysql -u root -p"${MYSQL_ROOT_PASSWORD:-}" \
--connect-timeout=5 -N -e 'SELECT 1' 2>/dev/null | grep -q '^1$'; then
pass "MySQL 查询响应正常"
else
fail "MySQL ping 失败"
fail "当前部署 MySQL 查询失败"
fi
else
warn "MySQL 容器未运行external 模式跳过此项)"
fi
# Redis
REDIS_CTR=$(docker ps --filter "name=redis" --filter "status=running" --format '{{.Names}}' 2>/dev/null | head -1)
REDIS_CTR="$(container_id redis)"
if [ -n "$REDIS_CTR" ]; then
PING=$(docker exec "$REDIS_CTR" redis-cli -a "${REDIS_PASSWORD:-}" --no-auth-warning PING 2>/dev/null | tr -d '\r')
if [ "$PING" = "PONG" ]; then
@ -291,7 +321,7 @@ NICK=""
if [ -n "$CAPTCHA_KEY" ]; then
# 从 Redis 读取验证码
REDIS_CTR=$(docker ps --filter "name=redis" --filter "status=running" --format '{{.Names}}' 2>/dev/null | head -1)
REDIS_CTR="$(container_id redis)"
if [ -n "$REDIS_CTR" ]; then
CAPTCHA_CODE=$(docker exec "$REDIS_CTR" redis-cli -a "${REDIS_PASSWORD:-}" --no-auth-warning \
GET "captcha:${CAPTCHA_KEY}" 2>/dev/null | tr -d '\r')
@ -365,7 +395,7 @@ except:
fi
# 从数据库查询已有 App
MYSQL_CTR=$(docker ps --filter "name=mysql" --filter "status=running" --format '{{.Names}}' 2>/dev/null | head -1)
MYSQL_CTR="$(container_id mysql)"
APP_KEYS=""
if [ -n "$MYSQL_CTR" ]; then
APP_KEYS=$(docker exec "$MYSQL_CTR" sh -c \