Files
web/restart.sh

264 lines
13 KiB
Bash
Executable File
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.
#!/usr/bin/env bash
# 仅不拉代码,其余与 pull-and-restart.sh 一致:构建到 deploy/ 并重启
# 用法cd 项目根 && ./restart.sh拉取后可直接执行无需 chmod
# 行尾LF
set -e
ROOT="${PROJECT_ROOT:-$(cd "$(dirname "$0")" && pwd)}"
cd "$ROOT"
run_sudo() { sudo "$@"; }
ensure_curl() {
if command -v curl >/dev/null 2>&1; then return 0; fi
echo "未检测到 curl正在安装..."
if command -v apt-get >/dev/null 2>&1; then run_sudo apt-get update -qq; run_sudo apt-get install -y curl
elif command -v dnf >/dev/null 2>&1; then run_sudo dnf install -y curl
elif command -v yum >/dev/null 2>&1; then run_sudo yum install -y curl
else echo "无法自动安装 curl."; exit 1; fi
echo "curl 已安装."
}
# ---------- 检测并安装 Docker用 run_sudo 检测,与后续 compose 一致;支持 Podman----------
ensure_docker() {
if command -v docker >/dev/null 2>&1 && run_sudo docker info >/dev/null 2>&1; then
echo "Docker 已就绪."
return 0
fi
if command -v docker >/dev/null 2>&1; then
echo "Docker/Podman 守护进程未连接,尝试启动..."
run_sudo systemctl start podman 2>/dev/null || true
run_sudo systemctl start docker 2>/dev/null || true
if run_sudo docker info >/dev/null 2>&1; then
echo "Docker 已就绪."
return 0
fi
echo "错误:无法连接 Docker/Podman 守护进程,请执行: sudo systemctl start podman 或 sudo systemctl start docker" >&2
exit 1
fi
echo "未检测到 Docker 或未启动,正在安装..."
if command -v apt-get >/dev/null 2>&1; then
run_sudo apt-get update -qq
run_sudo apt-get install -y docker.io docker-compose-plugin 2>/dev/null || run_sudo apt-get install -y docker.io docker-compose
run_sudo systemctl start docker
run_sudo systemctl enable docker
elif command -v dnf >/dev/null 2>&1 || command -v yum >/dev/null 2>&1; then
if command -v dnf >/dev/null 2>&1; then
run_sudo dnf install -y docker
else
run_sudo yum install -y docker
fi
run_sudo systemctl start docker
run_sudo systemctl enable docker
else
echo "无法自动安装 Docker请先安装 Docker 与 Docker Compose 后重试."
exit 1
fi
echo "Docker 安装完成."
}
ensure_registry_mirror() {
REG_CONF_D="/etc/containers/registries.conf.d"
REG_MIRROR_CONF="$REG_CONF_D/99-docker-mirror.conf"
echo "配置 Docker Hub 镜像加速Podman..."
run_sudo mkdir -p "$REG_CONF_D"
run_sudo tee "$REG_MIRROR_CONF" >/dev/null <<'REGEOF'
# 国内 Docker Hub 拉取加速,多镜像备用
unqualified-search-registries = ["docker.io"]
[[registry]]
location = "docker.io"
[[registry.mirror]]
location = "docker.m.daocloud.io"
[[registry.mirror]]
location = "docker.1ms.run"
[[registry.mirror]]
location = "docker.xuanyuan.me"
REGEOF
echo "已写入 $REG_MIRROR_CONF"
}
ensure_docker_compose() {
run_sudo docker compose version >/dev/null 2>&1 && return 0
command -v docker-compose >/dev/null 2>&1 && return 0
[ -x /usr/local/bin/docker-compose ] && return 0
echo "未检测到 Docker Compose正在尝试安装优先插件..."
if command -v dnf >/dev/null 2>&1; then
run_sudo dnf install -y docker-compose-plugin 2>/dev/null || true
if ! run_sudo docker compose version >/dev/null 2>&1; then
echo "系统源无插件,尝试添加 Docker CE 源(阿里云镜像)..."
run_sudo dnf install -y dnf-plugins-core 2>/dev/null || true
run_sudo dnf config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 2>/dev/null || \
run_sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 2>/dev/null || true
run_sudo dnf install -y docker-compose-plugin 2>/dev/null || true
fi
elif command -v yum >/dev/null 2>&1; then
run_sudo yum install -y docker-compose-plugin 2>/dev/null || true
if ! run_sudo docker compose version >/dev/null 2>&1; then
echo "系统源无插件,尝试添加 Docker CE 源(阿里云镜像)..."
run_sudo yum install -y yum-utils 2>/dev/null || true
run_sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 2>/dev/null || \
run_sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 2>/dev/null || true
run_sudo yum install -y docker-compose-plugin 2>/dev/null || true
fi
elif command -v apt-get >/dev/null 2>&1; then
run_sudo apt-get update -qq 2>/dev/null; run_sudo apt-get install -y docker-compose-plugin 2>/dev/null || true
fi
run_sudo docker compose version >/dev/null 2>&1 && echo "Docker Compose 插件已就绪." && return 0
echo "正在安装独立版 Docker Compose国内 DaoCloud 镜像)..."
COMPOSE_ARCH="$(uname -m)"
case "$COMPOSE_ARCH" in
x86_64) COMPOSE_ARCH=x86_64 ;;
aarch64|arm64) COMPOSE_ARCH=aarch64 ;;
*) COMPOSE_ARCH=x86_64 ;;
esac
COMPOSE_VER="v2.24.0"
COMPOSE_URL_CN="https://get.daocloud.io/docker/compose/releases/download/${COMPOSE_VER}/docker-compose-linux-${COMPOSE_ARCH}"
if ! run_sudo curl -sfL --connect-timeout 20 --max-time 90 "$COMPOSE_URL_CN" -o /usr/local/bin/docker-compose; then
COMPOSE_URL="https://github.com/docker/compose/releases/download/${COMPOSE_VER}/docker-compose-linux-${COMPOSE_ARCH}"
run_sudo curl -sfL --max-time 90 "$COMPOSE_URL" -o /usr/local/bin/docker-compose
fi
run_sudo chmod +x /usr/local/bin/docker-compose
run_sudo /usr/local/bin/docker-compose version >/dev/null 2>&1 || { run_sudo rm -f /usr/local/bin/docker-compose; echo "独立版运行失败(可能架构不符),请尝试: dnf install -y docker-compose-plugin 或 yum install -y docker-compose-plugin" >&2; return 0; }
echo "Docker Compose 已安装."
}
# ---------- 检测并安装 Nginx反代 + 强制 HTTPS----------
ensure_nginx() {
command -v nginx >/dev/null 2>&1 && return 0
echo "未检测到 Nginx正在安装..."
if command -v apt-get >/dev/null 2>&1; then run_sudo apt-get update -qq; run_sudo apt-get install -y nginx
elif command -v dnf >/dev/null 2>&1; then run_sudo dnf install -y nginx
elif command -v yum >/dev/null 2>&1; then run_sudo yum install -y nginx
else echo "无法自动安装 Nginx."; exit 1; fi
run_sudo systemctl enable nginx 2>/dev/null || true
run_sudo systemctl start nginx 2>/dev/null || true
echo "Nginx 已安装."
}
ensure_curl
ensure_docker
ensure_docker_compose
ensure_registry_mirror
ensure_nginx
resolve_compose_cmd() {
run_sudo docker compose version >/dev/null 2>&1 && echo "docker compose" && return
if [ -x /usr/local/bin/docker-compose ]; then
r=0; run_sudo /usr/local/bin/docker-compose version >/dev/null 2>&1 || r=1
if [ "$r" -eq 0 ]; then echo "/usr/local/bin/docker-compose"; return; fi
echo "检测到 /usr/local/bin/docker-compose 无法运行(可能架构不符),正在重装..." >&2
run_sudo rm -f /usr/local/bin/docker-compose
ensure_docker_compose || true
fi
run_sudo docker-compose version >/dev/null 2>&1 && echo "docker-compose" && return
ensure_docker_compose || true
run_sudo docker compose version >/dev/null 2>&1 && echo "docker compose" && return
if [ -x /usr/local/bin/docker-compose ]; then
r=0; run_sudo /usr/local/bin/docker-compose version >/dev/null 2>&1 || r=1
[ "$r" -eq 0 ] && echo "/usr/local/bin/docker-compose" || echo ""
else
echo ""
fi
}
COMPOSE_CMD=""
compose_cmd() {
if [ -z "$COMPOSE_CMD" ]; then COMPOSE_CMD="$(resolve_compose_cmd)"; fi
if [ -z "$COMPOSE_CMD" ]; then echo "错误:无法找到 docker compose请手动安装到 /usr/local/bin/docker-compose"; exit 1; fi
run_sudo env REGISTRY_MIRROR="${REGISTRY_MIRROR}" GOPROXY="${GOPROXY}" $COMPOSE_CMD "$@"
}
echo "重启 yh_web ($ROOT)(不拉代码,仅构建并启动)..."
# 环境配置:缺失时从 server/.env.example 复制
if [ ! -f server/.env ]; then
if [ -f server/.env.example ]; then
cp server/.env.example server/.env
echo "已从 server/.env.example 创建 server/.env"
else
mkdir -p server
ND="${NGINX_DOMAIN:-yuheng.yuxindazhineng.com}"
printf 'MONGODB_URI=mongodb://mongo:27017\nMONGODB_DB=yxd-agent-testing\nPORT=8088\nGIN_MODE=release\nALLOWED_ORIGINS=https://%s\n' "$ND" > server/.env
echo "已创建默认 server/.env"
fi
fi
[ -f server/.env ] && sed -i 's/\r$//' server/.env 2>/dev/null || true
[ -f server/.env ] && set -a && source server/.env && set +a
export GOPROXY="${GOPROXY:-https://goproxy.cn,direct}"
export REGISTRY_MIRROR="${REGISTRY_MIRROR:-docker.m.daocloud.io/library/}"
# 与 pull-and-restart 一致:宿主机 9527 检查
if grep -q '9527' "$ROOT/docker-compose.yml" 2>/dev/null; then
echo "错误: docker-compose.yml 仍含 9527会与 sshd 冲突。请拉取最新代码后再执行。" >&2
exit 1
fi
# 构建到 deploy/(与 pull-and-restart.sh 相同,仅无 git 拉取)
mkdir -p "$ROOT/deploy/web/dist" "$ROOT/deploy/admin/dist" "$ROOT/deploy/api"
echo "构建 web 前端 -> deploy/web/dist ..."
run_sudo docker run --rm -v "$ROOT/web:/app" -v "$ROOT/deploy/web/dist:/out" -w /app \
"${REGISTRY_MIRROR}node:20-alpine" sh -c "rm -rf /out/* 2>/dev/null; (npm ci --legacy-peer-deps 2>/dev/null || npm install --legacy-peer-deps) && npm run build && cp -r dist/. /out/"
# 与 pull-and-restart 一致:文档根是 deploy/web/dist须把 promotion含 social 视频)拷入 dist
echo "同步 web/promotion -> deploy/web/dist/promotion ..."
mkdir -p "$ROOT/deploy/web/dist/promotion"
if command -v rsync >/dev/null 2>&1; then
rsync -a --exclude='_pptx_extract/' --exclude='视频发布/' \
"$ROOT/web/promotion/" "$ROOT/deploy/web/dist/promotion/"
else
mkdir -p "$ROOT/deploy/web/dist/promotion/social"
cp -a "$ROOT/web/promotion/social/." "$ROOT/deploy/web/dist/promotion/social/" 2>/dev/null || true
[ -f "$ROOT/web/promotion/logo.png" ] && cp -a "$ROOT/web/promotion/logo.png" "$ROOT/deploy/web/dist/promotion/" || true
[ -f "$ROOT/web/promotion/index.html" ] && cp -a "$ROOT/web/promotion/index.html" "$ROOT/deploy/web/dist/promotion/" || true
fi
echo "构建 admin 前端 -> deploy/admin/dist ..."
run_sudo docker run --rm -v "$ROOT/admin:/app" -v "$ROOT/deploy/admin/dist:/out" -w /app \
"${REGISTRY_MIRROR}node:20-alpine" sh -c "rm -rf /out/* 2>/dev/null; (npm ci --legacy-peer-deps 2>/dev/null || npm install --legacy-peer-deps) && npm run build && cp -r dist/. /out/"
echo "构建 api 二进制 -> deploy/api/server ..."
run_sudo docker run --rm -v "$ROOT/server:/src" -v "$ROOT/deploy/api:/out" -w /src -e GOPROXY="${GOPROXY}" \
"${REGISTRY_MIRROR}golang:1.21-alpine" sh -c "go build -mod=vendor -o /out/server ."
run_sudo chmod -R a+rX "$ROOT/deploy/web/dist" "$ROOT/deploy/admin/dist" 2>/dev/null || true
if [ ! -f "$ROOT/deploy/web/dist/index.html" ] || [ ! -f "$ROOT/deploy/admin/dist/index.html" ]; then
echo "错误: 构建产物不完整(缺少 index.html请检查上方构建日志。" >&2
exit 1
fi
compose_cmd build api
MONGO_IMAGE="${REGISTRY_MIRROR}mongo:7"
if ! run_sudo docker image inspect "$MONGO_IMAGE" >/dev/null 2>&1; then
echo "拉取 mongo 镜像(仅首次或镜像缺失时)..."
run_sudo docker pull "$MONGO_IMAGE" || true
else
echo "mongo 镜像已存在,跳过拉取."
fi
NGINX_DOMAIN="${NGINX_DOMAIN:-yuheng.yuxindazhineng.com}"
NGINX_SSL_DIR="/etc/ssl/yh_web/$NGINX_DOMAIN"
NGINX_CONF_NAME="${NGINX_DOMAIN}.conf"
run_sudo mkdir -p "$NGINX_SSL_DIR"
if [ -f "$ROOT/nginx/$NGINX_DOMAIN.pem" ] && [ -f "$ROOT/nginx/$NGINX_DOMAIN.key" ]; then
run_sudo cp -f "$ROOT/nginx/$NGINX_DOMAIN.pem" "$NGINX_SSL_DIR/fullchain.pem"
run_sudo cp -f "$ROOT/nginx/$NGINX_DOMAIN.key" "$NGINX_SSL_DIR/privkey.pem"
run_sudo chmod 644 "$NGINX_SSL_DIR/fullchain.pem"
run_sudo chmod 600 "$NGINX_SSL_DIR/privkey.pem"
elif [ -f "$ROOT/nginx/fullchain.pem" ] && [ -f "$ROOT/nginx/privkey.pem" ]; then
run_sudo cp -f "$ROOT/nginx/fullchain.pem" "$ROOT/nginx/privkey.pem" "$NGINX_SSL_DIR/"
run_sudo chmod 644 "$NGINX_SSL_DIR/fullchain.pem"
run_sudo chmod 600 "$NGINX_SSL_DIR/privkey.pem" 2>/dev/null || true
elif [ -f "$ROOT/nginx/$NGINX_DOMAIN/fullchain.pem" ] && [ -f "$ROOT/nginx/$NGINX_DOMAIN/privkey.pem" ]; then
run_sudo cp -f "$ROOT/nginx/$NGINX_DOMAIN/fullchain.pem" "$ROOT/nginx/$NGINX_DOMAIN/privkey.pem" "$NGINX_SSL_DIR/"
run_sudo chmod 644 "$NGINX_SSL_DIR/fullchain.pem"
run_sudo chmod 600 "$NGINX_SSL_DIR/privkey.pem" 2>/dev/null || true
fi
compose_cmd down 2>/dev/null || true
compose_cmd up -d --force-recreate
bash "$ROOT/scripts/run-promotion-import-on-deploy.sh" "$ROOT"
if [ -f "$ROOT/nginx/$NGINX_CONF_NAME" ]; then
run_sudo cp -f "$ROOT/nginx/$NGINX_CONF_NAME" /etc/nginx/conf.d/ 2>/dev/null || true
if run_sudo nginx -t 2>/dev/null; then
run_sudo systemctl reload nginx 2>/dev/null && echo "Nginx 已重载." || true
fi
fi
echo "完成. 对外仅 443反代: https://$NGINX_DOMAIN"