Files
web/pull-and-restart.sh

313 lines
13 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.
#!/usr/bin/env bash
# 拉取代码并重启缺什么自动安装curl、Git、Docker、Docker Compose再 git 拉取 + docker compose 构建启动
# 用法cd 项目根 && chmod +x pull-and-restart.sh && ./pull-and-restart.sh
# 行尾LF
set -e
ROOT="${PROJECT_ROOT:-$(cd "$(dirname "$0")" && pwd)}"
cd "$ROOT"
run_sudo() { sudo "$@"; }
# ---------- 检测并安装 curl下载 Docker Compose 等需要)----------
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请先安装 curl 后重试."
exit 1
fi
echo "curl 已安装."
}
# ---------- 检测并安装 Git国内服务器用系统源----------
ensure_git() {
if command -v git >/dev/null 2>&1; then
return 0
fi
echo "未检测到 Git正在安装..."
if command -v apt-get >/dev/null 2>&1; then
run_sudo apt-get update -qq
run_sudo apt-get install -y git
elif command -v dnf >/dev/null 2>&1; then
run_sudo dnf install -y git
elif command -v yum >/dev/null 2>&1; then
run_sudo yum install -y git
else
echo "无法自动安装 Git请先安装 Git 后重试."
exit 1
fi
echo "Git 已安装."
}
# ---------- 检测并安装 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 安装完成."
}
# ---------- 配置 Docker Hub 镜像加速(国内拉取超时时使用 Podman 镜像)----------
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 拉取加速,由 pull-and-restart.sh 生成(多镜像备用)
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_CONFdocker.io 镜像: daocloud / 1ms / xuanyuan."
}
# ---------- 检测并安装 Docker Compose优先插件 docker compose否则独立二进制----------
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
# 优先尝试用包管理器安装插件,避免独立二进制架构不符导致 Bus error
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
# 回退:下载独立版(国内 DaoCloud 镜像)
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
# 若运行即崩溃(如 Bus error删除以免后续误用
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证书按域名存 /etc/ssl/yh_web/<域名>/----------
ensure_nginx() {
if command -v nginx >/dev/null 2>&1; then
return 0
fi
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_git
ensure_docker
ensure_docker_compose
ensure_registry_mirror
ensure_nginx
# 确定要用的 compose 命令;测试独立二进制时用 || true 避免 Bus error 导致脚本退出
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
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 或 docker-compose请手动安装到 /usr/local/bin/docker-compose"
exit 1
fi
# sudo 默认不传环境变量,显式传入以便 compose 使用 REGISTRY_MIRROR / GOPROXY
run_sudo env REGISTRY_MIRROR="${REGISTRY_MIRROR}" GOPROXY="${GOPROXY}" $COMPOSE_CMD "$@"
}
echo "=========================================="
echo " yh_web 拉取并重启"
echo " 路径: $ROOT"
echo "=========================================="
# 环境配置:缺失时从 server/.env.example 复制Docker 部署用 mongo:27017
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
NGINX_DEFAULT_DOMAIN="${NGINX_DOMAIN:-yuheng.yuxindazhineng.com}"
cat > server/.env <<ENVEOF
MONGODB_URI=mongodb://mongo:27017
MONGODB_DB=yxd-agent-testing
PORT=9527
GIN_MODE=release
ALLOWED_ORIGINS=https://${NGINX_DEFAULT_DOMAIN}
ENVEOF
echo "已创建默认 server/.envALLOWED_ORIGINS=https://${NGINX_DEFAULT_DOMAIN}),可按需修改."
fi
fi
[ -f server/.env ] && sed -i 's/\r$//' server/.env
[ -f server/.env ] && set -a && source server/.env && set +a
BRANCH="${GIT_BRANCH:-master}"
echo "[1/3] 拉取代码..."
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
git fetch origin --progress
git reset --hard "origin/$BRANCH"
else
echo "未检测到 Git 仓库,正在克隆..."
export GIT_TERMINAL_PROMPT=0
# 默认仓库地址(仅本地/服务器使用不提交到仓库可覆盖export GIT_REPO_URL=...
REPO_URL="${GIT_REPO_URL:-https://whm:02f8ceeee5f1aeb197ff400e4d97abbcf5550015@gitea.yuxindazhineng.com/whm/web.git}"
SELF="$(basename "$0")"
tmp_backup="/tmp/yh_web_deploy_$$"
mkdir -p "$tmp_backup"
[ -f "$SELF" ] && cp -a "$SELF" "$tmp_backup/"
[ -f server/.env ] && cp -a server/.env "$tmp_backup/" 2>/dev/null || true
git init -b "$BRANCH"
git remote add origin "$REPO_URL"
git fetch origin --progress
git reset --hard "origin/$BRANCH"
[ -f "$tmp_backup/$SELF" ] && cp -a "$tmp_backup/$SELF" "$SELF" && chmod +x "$SELF"
[ -f "$tmp_backup/.env" ] && mkdir -p server && cp -a "$tmp_backup/.env" server/.env
rm -rf "$tmp_backup"
fi
echo ""
echo "[2/3] 重新构建并启动..."
export GOPROXY="${GOPROXY:-https://goproxy.cn,direct}"
# 国内直连 Docker Hub 超时时用镜像拉取基础镜像Dockerfile FROM 与 mongo 镜像)
export REGISTRY_MIRROR="${REGISTRY_MIRROR:-docker.m.daocloud.io/library/}"
compose_cmd build --no-cache
# 先显式从镜像站拉 mongo避免 compose up 时直连 Docker Hub 超时
echo "拉取 mongo 镜像..."
run_sudo docker pull "${REGISTRY_MIRROR}mongo:7" || true
# 证书目录在 compose up 前就要就绪compose 内 nginx 容器会挂载)
NGINX_DOMAIN="${NGINX_DOMAIN:-yuheng.yuxindazhineng.com}"
NGINX_SSL_DIR="/etc/ssl/yh_web/$NGINX_DOMAIN"
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"
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"
fi
compose_cmd up -d --force-recreate
echo ""
echo "[3/3] 证书与宿主机 Nginx可选..."
NGINX_CONF_NAME="${NGINX_DOMAIN}.conf"
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 ""
echo "完成. 对外仅 443反代: https://$NGINX_DOMAIN"