From 809c735498ccc77f1fa359ef109cefdd6e8a5a8d Mon Sep 17 00:00:00 2001 From: yuyx <237899745@qq.com> Date: Mon, 15 Dec 2025 13:57:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=80=E9=94=AE=E9=83=A8?= =?UTF-8?q?=E7=BD=B2=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- install.sh | 417 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 417 insertions(+) create mode 100755 install.sh diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..3b1ed40 --- /dev/null +++ b/install.sh @@ -0,0 +1,417 @@ +#!/bin/bash +# zsglpt 一键部署脚本 +# 用法: curl -sSL https://your-domain/install.sh | bash +# 或: bash install.sh [install|uninstall|ssl|status] + +set -e + +# ==================== 配置 ==================== +APP_NAME="zsglpt" +APP_PORT="51233" +CONTAINER_NAME="knowledge-automation-multiuser" +GIT_REPO="https://git.workyai.cn/237899745/zsglpt.git" +INSTALL_DIR="/opt/$APP_NAME" + +# ==================== 颜色 ==================== +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +log_info() { echo -e "${GREEN}[INFO]${NC} $1"; } +log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } +log_error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; } +log_step() { echo -e "${BLUE}[STEP]${NC} $1"; } + +# ==================== 检测环境 ==================== +detect_os() { + if [ -f /etc/os-release ]; then + . /etc/os-release + OS=$ID + else + log_error "无法检测操作系统" + fi +} + +detect_bt_panel() { + if [ -d "/www/server/panel" ] && [ -f "/etc/init.d/bt" ]; then + BT_PANEL=true + BT_NGINX_VHOST="/www/server/panel/vhost/nginx" + BT_NGINX_BIN="/www/server/nginx/sbin/nginx" + log_info "检测到宝塔面板" + else + BT_PANEL=false + log_info "未检测到宝塔面板,使用系统 nginx" + fi +} + +check_root() { + if [ "$EUID" -ne 0 ]; then + log_error "请使用 root 用户运行此脚本" + fi +} + +# ==================== 安装依赖 ==================== +install_deps() { + log_step "安装依赖..." + + if command -v apt &> /dev/null; then + apt update -qq + apt install -y -qq git curl docker.io docker-compose nginx certbot python3-certbot-nginx 2>/dev/null || true + elif command -v yum &> /dev/null; then + yum install -y -q git curl docker docker-compose nginx certbot python3-certbot-nginx 2>/dev/null || true + fi + + # 启动 docker + systemctl enable docker 2>/dev/null || true + systemctl start docker 2>/dev/null || true +} + +# ==================== 交互式配置 ==================== +get_config() { + echo "" + echo -e "${BLUE}========== $APP_NAME 部署配置 ==========${NC}" + echo "" + + # 域名 + read -p "请输入域名 (例: zsglpt.example.com): " DOMAIN + if [ -z "$DOMAIN" ]; then + log_error "域名不能为空" + fi + + # 端口 + read -p "请输入服务端口 [默认: $APP_PORT]: " INPUT_PORT + APP_PORT=${INPUT_PORT:-$APP_PORT} + + # Git 认证 + read -p "Git 用户名 [默认: 237899745]: " GIT_USER + GIT_USER=${GIT_USER:-237899745} + + read -sp "Git 密码: " GIT_PASS + echo "" + if [ -z "$GIT_PASS" ]; then + log_error "Git 密码不能为空" + fi + + # SSL + read -p "是否配置 SSL? [Y/n]: " SETUP_SSL + SETUP_SSL=${SETUP_SSL:-Y} + + if [[ "$SETUP_SSL" =~ ^[Yy]$ ]]; then + read -p "SSL 证书邮箱 (用于 Let's Encrypt): " SSL_EMAIL + SSL_EMAIL=${SSL_EMAIL:-admin@$DOMAIN} + fi + + # 确认 + echo "" + echo -e "${YELLOW}========== 配置确认 ==========${NC}" + echo "域名: $DOMAIN" + echo "端口: $APP_PORT" + echo "安装目录: $INSTALL_DIR" + echo "SSL: $SETUP_SSL" + echo "" + read -p "确认安装? [Y/n]: " CONFIRM + if [[ ! "$CONFIRM" =~ ^[Yy]?$ ]]; then + log_error "安装已取消" + fi +} + +# ==================== 克隆代码 ==================== +clone_repo() { + log_step "克隆代码..." + + if [ -d "$INSTALL_DIR" ]; then + log_warn "目录已存在,更新代码..." + cd "$INSTALL_DIR" + git fetch origin + git reset --hard origin/master + else + GIT_URL="https://${GIT_USER}:${GIT_PASS}@git.workyai.cn/237899745/zsglpt.git" + git clone "$GIT_URL" "$INSTALL_DIR" + cd "$INSTALL_DIR" + fi + + # 保存配置 + cat > "$INSTALL_DIR/.deploy_config" << EOF +DOMAIN=$DOMAIN +APP_PORT=$APP_PORT +GIT_USER=$GIT_USER +SSL_EMAIL=$SSL_EMAIL +INSTALL_TIME=$(date '+%Y-%m-%d %H:%M:%S') +EOF +} + +# ==================== Docker 部署 ==================== +deploy_docker() { + log_step "部署 Docker 容器..." + + cd "$INSTALL_DIR" + + # 修改 docker-compose 端口映射 + if [ -f docker-compose.yml ]; then + sed -i "s/51232:51233/${APP_PORT}:51233/g" docker-compose.yml + fi + + # 构建并启动 + docker-compose down 2>/dev/null || true + docker-compose up -d --build + + log_info "等待容器启动..." + sleep 8 + + if docker ps | grep -q "$CONTAINER_NAME"; then + log_info "容器启动成功" + else + log_error "容器启动失败,请检查日志: docker logs $CONTAINER_NAME" + fi +} + +# ==================== Nginx 配置 ==================== +setup_nginx() { + log_step "配置 Nginx..." + + if $BT_PANEL; then + NGINX_CONF="$BT_NGINX_VHOST/${DOMAIN}.conf" + NGINX_CMD="$BT_NGINX_BIN" + else + NGINX_CONF="/etc/nginx/sites-available/${DOMAIN}.conf" + NGINX_CMD="nginx" + fi + + # 生成配置 + cat > "$NGINX_CONF" << EOF +# $APP_NAME - $DOMAIN +# 由 install.sh 自动生成,请勿手动修改 + +server { + listen 80; + server_name $DOMAIN; + + location / { + proxy_pass http://127.0.0.1:$APP_PORT; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto \$scheme; + proxy_read_timeout 86400; + proxy_send_timeout 86400; + } +} +EOF + + # 非宝塔环境需要创建软链接 + if ! $BT_PANEL; then + ln -sf "$NGINX_CONF" "/etc/nginx/sites-enabled/${DOMAIN}.conf" 2>/dev/null || true + fi + + # 测试并重载 + $NGINX_CMD -t && $NGINX_CMD -s reload + log_info "Nginx 配置完成" +} + +# ==================== SSL 配置 ==================== +setup_ssl() { + if [[ ! "$SETUP_SSL" =~ ^[Yy]$ ]]; then + return + fi + + log_step "配置 SSL 证书..." + + if $BT_PANEL; then + # 宝塔面板使用 acme.sh + if [ -f "/root/.acme.sh/acme.sh" ]; then + /root/.acme.sh/acme.sh --issue -d "$DOMAIN" --webroot "$INSTALL_DIR/static" --force || true + + # 更新 nginx 配置 + NGINX_CONF="$BT_NGINX_VHOST/${DOMAIN}.conf" + cat > "$NGINX_CONF" << EOF +# $APP_NAME - $DOMAIN (SSL) +# 由 install.sh 自动生成 + +server { + listen 80; + server_name $DOMAIN; + return 301 https://\$host\$request_uri; +} + +server { + listen 443 ssl http2; + server_name $DOMAIN; + + ssl_certificate /root/.acme.sh/${DOMAIN}_ecc/fullchain.cer; + ssl_certificate_key /root/.acme.sh/${DOMAIN}_ecc/${DOMAIN}.key; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; + ssl_prefer_server_ciphers on; + + location / { + proxy_pass http://127.0.0.1:$APP_PORT; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto \$scheme; + proxy_read_timeout 86400; + } +} +EOF + $BT_NGINX_BIN -t && $BT_NGINX_BIN -s reload + else + log_warn "未找到 acme.sh,请在宝塔面板手动配置 SSL" + fi + else + # 使用 certbot + certbot --nginx -d "$DOMAIN" --non-interactive --agree-tos -m "$SSL_EMAIL" || log_warn "SSL 配置失败,请手动配置" + fi + + log_info "SSL 配置完成" +} + +# ==================== 卸载 ==================== +uninstall() { + echo -e "${RED}========== 卸载 $APP_NAME ==========${NC}" + + # 读取配置 + if [ -f "$INSTALL_DIR/.deploy_config" ]; then + source "$INSTALL_DIR/.deploy_config" + else + read -p "请输入域名: " DOMAIN + fi + + read -p "确认卸载 $APP_NAME? 数据将被删除! [y/N]: " CONFIRM + if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then + log_info "卸载已取消" + exit 0 + fi + + log_step "停止容器..." + cd "$INSTALL_DIR" 2>/dev/null && docker-compose down 2>/dev/null || true + docker rm -f "$CONTAINER_NAME" 2>/dev/null || true + + log_step "删除 Nginx 配置..." + detect_bt_panel + if $BT_PANEL; then + rm -f "$BT_NGINX_VHOST/${DOMAIN}.conf" + $BT_NGINX_BIN -s reload 2>/dev/null || true + else + rm -f "/etc/nginx/sites-available/${DOMAIN}.conf" + rm -f "/etc/nginx/sites-enabled/${DOMAIN}.conf" + nginx -s reload 2>/dev/null || true + fi + + # 备份数据 + if [ -d "$INSTALL_DIR/data" ]; then + BACKUP_DIR="/root/${APP_NAME}_backup_$(date +%Y%m%d_%H%M%S)" + log_step "备份数据到 $BACKUP_DIR..." + mkdir -p "$BACKUP_DIR" + cp -r "$INSTALL_DIR/data" "$BACKUP_DIR/" + fi + + log_step "删除安装目录..." + rm -rf "$INSTALL_DIR" + + log_info "卸载完成!" + [ -d "$BACKUP_DIR" ] && log_info "数据已备份到: $BACKUP_DIR" +} + +# ==================== 状态检查 ==================== +status() { + echo -e "${BLUE}========== $APP_NAME 状态 ==========${NC}" + + if [ -f "$INSTALL_DIR/.deploy_config" ]; then + source "$INSTALL_DIR/.deploy_config" + echo "域名: $DOMAIN" + echo "端口: $APP_PORT" + echo "安装时间: $INSTALL_TIME" + fi + + echo "" + echo "容器状态:" + docker ps -a | grep "$CONTAINER_NAME" || echo "容器未运行" + + echo "" + echo "最近日志:" + docker logs --tail 10 "$CONTAINER_NAME" 2>/dev/null || echo "无日志" +} + +# ==================== 更新 ==================== +update() { + log_step "更新 $APP_NAME..." + + if [ ! -d "$INSTALL_DIR" ]; then + log_error "未找到安装目录,请先安装" + fi + + cd "$INSTALL_DIR" + + # 备份数据库 + if [ -f "data/app_data.db" ]; then + cp "data/app_data.db" "data/app_data.db.$(date +%Y%m%d_%H%M%S).bak" + fi + + # 拉取代码 + git fetch origin + git reset --hard origin/master + + # 重建容器 + docker-compose down + docker-compose up -d --build + + log_info "更新完成!" +} + +# ==================== 主函数 ==================== +main() { + check_root + detect_os + detect_bt_panel + + case "${1:-install}" in + install) + install_deps + get_config + clone_repo + deploy_docker + setup_nginx + setup_ssl + echo "" + echo -e "${GREEN}========== 安装完成 ==========${NC}" + echo "访问地址: http://$DOMAIN" + [[ "$SETUP_SSL" =~ ^[Yy]$ ]] && echo "HTTPS: https://$DOMAIN" + echo "" + ;; + uninstall) + uninstall + ;; + update) + update + ;; + status) + status + ;; + ssl) + if [ -f "$INSTALL_DIR/.deploy_config" ]; then + source "$INSTALL_DIR/.deploy_config" + fi + SETUP_SSL=Y + setup_ssl + ;; + *) + echo "用法: $0 [install|uninstall|update|status|ssl]" + echo "" + echo " install - 安装部署 (默认)" + echo " uninstall - 卸载并备份数据" + echo " update - 更新到最新版本" + echo " status - 查看运行状态" + echo " ssl - 配置/更新 SSL 证书" + ;; + esac +} + +main "$@"