#!/bin/bash ################################################################################ # 玩玩云 (WanWanYun) - 一键部署脚本 # 项目地址: https://gitee.com/yu-yon/vue-driven-cloud-storage # 版本: v1.0.0 ################################################################################ set -e # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' WHITE='\033[1;37m' NC='\033[0m' # No Color # 全局变量 PROJECT_NAME="wanwanyun" PROJECT_DIR="/var/www/${PROJECT_NAME}" REPO_URL="https://gitee.com/yu-yon/vue-driven-cloud-storage.git" NODE_VERSION="18" ADMIN_USERNAME="" ADMIN_PASSWORD="" DOMAIN="" USE_DOMAIN=false SSL_METHOD="" ################################################################################ # 工具函数 ################################################################################ print_banner() { clear echo -e "${CYAN}" echo "╔═══════════════════════════════════════════════════════════════╗" echo "║ ║" echo "║ 🌩️ 玩玩云 一键部署脚本 ║" echo "║ ║" echo "║ Cloud Storage Platform ║" echo "║ ║" echo "╚═══════════════════════════════════════════════════════════════╝" echo -e "${NC}" } print_step() { echo -e "\n${BLUE}▶ $1${NC}" } print_success() { echo -e "${GREEN}✓ $1${NC}" } print_error() { echo -e "${RED}✗ $1${NC}" } print_warning() { echo -e "${YELLOW}⚠ $1${NC}" } print_info() { echo -e "${CYAN}ℹ $1${NC}" } # 检测操作系统 detect_os() { if [[ -f /etc/os-release ]]; then . /etc/os-release OS=$ID OS_VERSION=$VERSION_ID else print_error "无法检测操作系统" exit 1 fi } # 检测系统架构 detect_arch() { ARCH=$(uname -m) case $ARCH in x86_64) ARCH="amd64" ;; aarch64) ARCH="arm64" ;; *) print_error "不支持的系统架构: $ARCH" exit 1 ;; esac } # 检测root权限 check_root() { if [[ $EUID -ne 0 ]]; then print_error "此脚本需要root权限运行" print_info "请使用: sudo bash install.sh" exit 1 fi } ################################################################################ # 环境检测 ################################################################################ system_check() { print_step "正在检测系统环境..." # 检测操作系统 detect_os print_success "操作系统: $OS $OS_VERSION" # 检测架构 detect_arch print_success "系统架构: $ARCH" # 检测内存 TOTAL_MEM=$(free -m | awk '/^Mem:/{print $2}') if [[ $TOTAL_MEM -lt 512 ]]; then print_warning "内存不足512MB,可能影响性能" else print_success "可用内存: ${TOTAL_MEM}MB" fi # 检测磁盘空间 DISK_AVAIL=$(df -m / | awk 'NR==2 {print $4}') if [[ $DISK_AVAIL -lt 2048 ]]; then print_warning "磁盘空间不足2GB,可能影响运行" else print_success "可用磁盘: ${DISK_AVAIL}MB" fi # 检测网络 if ping -c 1 gitee.com &> /dev/null; then print_success "网络连接正常" else print_error "无法连接到网络" exit 1 fi # 检测公网IP PUBLIC_IP=$(curl -s ifconfig.me || curl -s icanhazip.com || echo "未知") print_info "公网IP: $PUBLIC_IP" echo "" } ################################################################################ # 软件源配置 ################################################################################ choose_mirror() { print_step "选择软件包安装源" echo "" echo "请选择软件源:" echo -e "${GREEN}[1]${NC} 官方源 (国外服务器推荐)" echo -e "${GREEN}[2]${NC} 阿里云镜像源 (国内服务器推荐,速度更快)" echo "" while true; do read -p "请输入选项 [1-2]: " mirror_choice case $mirror_choice in 1) print_info "使用官方源" USE_ALIYUN_MIRROR=false break ;; 2) print_info "使用阿里云镜像源" USE_ALIYUN_MIRROR=true configure_aliyun_mirror break ;; *) print_error "无效选项,请重新选择" ;; esac done echo "" } configure_aliyun_mirror() { print_step "配置阿里云镜像源..." case $OS in ubuntu|debian) # 备份原有源 if [[ ! -f /etc/apt/sources.list.bak ]]; then cp /etc/apt/sources.list /etc/apt/sources.list.bak fi # 配置阿里云源 cat > /etc/apt/sources.list << EOF deb http://mirrors.aliyun.com/$OS/ $(lsb_release -cs) main restricted universe multiverse deb http://mirrors.aliyun.com/$OS/ $(lsb_release -cs)-updates main restricted universe multiverse deb http://mirrors.aliyun.com/$OS/ $(lsb_release -cs)-backports main restricted universe multiverse deb http://mirrors.aliyun.com/$OS/ $(lsb_release -cs)-security main restricted universe multiverse EOF print_success "阿里云源配置完成" ;; centos|rhel) # CentOS配置 if [[ ! -f /etc/yum.repos.d/CentOS-Base.repo.bak ]]; then cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak fi curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo yum clean all yum makecache print_success "阿里云源配置完成" ;; esac } ################################################################################ # 安装依赖环境 ################################################################################ install_dependencies() { print_step "正在安装依赖环境..." case $OS in ubuntu|debian) apt-get update apt-get install -y curl wget git unzip install_nodejs_apt install_nginx_apt ;; centos|rhel) yum install -y curl wget git unzip install_nodejs_yum install_nginx_yum ;; esac install_pm2 print_success "依赖环境安装完成" echo "" } install_nodejs_apt() { if command -v node &> /dev/null; then NODE_VER=$(node -v | cut -d'v' -f2 | cut -d'.' -f1) if [[ $NODE_VER -ge 18 ]]; then print_success "Node.js 已安装: $(node -v)" return fi fi print_info "正在安装 Node.js ${NODE_VERSION}.x..." curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - apt-get install -y nodejs print_success "Node.js 安装完成: $(node -v)" } install_nodejs_yum() { if command -v node &> /dev/null; then NODE_VER=$(node -v | cut -d'v' -f2 | cut -d'.' -f1) if [[ $NODE_VER -ge 18 ]]; then print_success "Node.js 已安装: $(node -v)" return fi fi print_info "正在安装 Node.js ${NODE_VERSION}.x..." curl -fsSL https://rpm.nodesource.com/setup_${NODE_VERSION}.x | bash - yum install -y nodejs print_success "Node.js 安装完成: $(node -v)" } install_nginx_apt() { if command -v nginx &> /dev/null; then print_success "Nginx 已安装: $(nginx -v 2>&1 | cut -d'/' -f2)" return fi print_info "正在安装 Nginx..." apt-get install -y nginx systemctl enable nginx print_success "Nginx 安装完成" } install_nginx_yum() { if command -v nginx &> /dev/null; then print_success "Nginx 已安装: $(nginx -v 2>&1 | cut -d'/' -f2)" return fi print_info "正在安装 Nginx..." yum install -y nginx systemctl enable nginx print_success "Nginx 安装完成" } install_pm2() { if command -v pm2 &> /dev/null; then print_success "PM2 已安装: $(pm2 -v)" return fi print_info "正在安装 PM2..." npm install -g pm2 pm2 startup print_success "PM2 安装完成" } ################################################################################ # 访问模式选择 ################################################################################ choose_access_mode() { print_step "选择访问模式" echo "" echo "请选择访问模式:" echo -e "${GREEN}[1]${NC} 域名模式 (推荐,支持HTTPS)" echo -e "${GREEN}[2]${NC} IP模式 (仅HTTP,适合测试)" echo "" while true; do read -p "请输入选项 [1-2]: " mode_choice case $mode_choice in 1) USE_DOMAIN=true configure_domain break ;; 2) USE_DOMAIN=false PUBLIC_IP=$(curl -s ifconfig.me || curl -s icanhazip.com || echo "未知") print_info "将使用 IP 模式访问: http://${PUBLIC_IP}" echo "" break ;; *) print_error "无效选项,请重新选择" ;; esac done } configure_domain() { echo "" while true; do read -p "请输入您的域名 (例如: wwy.example.com): " DOMAIN if [[ -z "$DOMAIN" ]]; then print_error "域名不能为空" continue fi # 验证域名格式 if [[ ! "$DOMAIN" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$ ]]; then print_error "域名格式不正确" continue fi # 验证域名解析 print_info "正在验证域名解析..." DOMAIN_IP=$(dig +short "$DOMAIN" | tail -n1) PUBLIC_IP=$(curl -s ifconfig.me || curl -s icanhazip.com) if [[ "$DOMAIN_IP" == "$PUBLIC_IP" ]]; then print_success "域名已正确解析到当前服务器IP" break else print_warning "域名未解析到当前服务器IP" print_info "域名解析IP: $DOMAIN_IP" print_info "当前服务器IP: $PUBLIC_IP" read -p "是否继续? (y/n): " continue_choice if [[ "$continue_choice" == "y" || "$continue_choice" == "Y" ]]; then break fi fi done choose_ssl_method } ################################################################################ # SSL证书配置 ################################################################################ choose_ssl_method() { echo "" print_step "选择SSL证书部署方式" echo "" echo -e "${YELLOW}【推荐方案】${NC}" echo -e "${GREEN}[1]${NC} Certbot (Let's Encrypt官方工具)" echo " - 最稳定可靠,支持自动续期" echo "" echo -e "${YELLOW}【备选方案】${NC}" echo -e "${GREEN}[2]${NC} acme.sh + Let's Encrypt" echo " - 纯Shell脚本,更轻量级" echo -e "${GREEN}[3]${NC} acme.sh + ZeroSSL" echo " - Let's Encrypt的免费替代品" echo -e "${GREEN}[4]${NC} acme.sh + Buypass" echo " - 挪威免费CA,有效期180天" echo "" echo -e "${YELLOW}【云服务商证书】${NC}" echo -e "${GREEN}[5]${NC} 阿里云免费证书 (需提供AccessKey)" echo -e "${GREEN}[6]${NC} 腾讯云免费证书 (需提供SecretKey)" echo "" echo -e "${YELLOW}【其他选项】${NC}" echo -e "${GREEN}[7]${NC} 使用已有证书 (手动上传)" echo -e "${GREEN}[8]${NC} 暂不配置HTTPS (可后续配置)" echo "" while true; do read -p "请输入选项 [1-8]: " ssl_choice case $ssl_choice in 1|2|3|4|5|6|7|8) SSL_METHOD=$ssl_choice break ;; *) print_error "无效选项,请重新选择" ;; esac done echo "" } deploy_ssl() { if [[ "$USE_DOMAIN" != "true" ]]; then return 0 fi case $SSL_METHOD in 1) deploy_certbot || ssl_fallback ;; 2) deploy_acme_letsencrypt || ssl_fallback ;; 3) deploy_acme_zerossl || ssl_fallback ;; 4) deploy_acme_buypass || ssl_fallback ;; 5) deploy_aliyun_ssl || ssl_fallback ;; 6) deploy_tencent_ssl || ssl_fallback ;; 7) deploy_manual_ssl ;; 8) print_info "跳过HTTPS配置" return 0 ;; esac } ssl_fallback() { print_error "SSL证书部署失败" echo "" print_warning "建议尝试备选方案:" echo -e "${GREEN}[2]${NC} acme.sh + Let's Encrypt (推荐)" echo -e "${GREEN}[3]${NC} acme.sh + ZeroSSL" echo -e "${GREEN}[4]${NC} acme.sh + Buypass" echo -e "${GREEN}[8]${NC} 暂不配置HTTPS" echo "" while true; do read -p "请选择备选方案 [2-4/8]: " retry_choice case $retry_choice in 2) deploy_acme_letsencrypt && return 0 ;; 3) deploy_acme_zerossl && return 0 ;; 4) deploy_acme_buypass && return 0 ;; 8) print_info "跳过HTTPS配置" SSL_METHOD=8 return 0 ;; *) print_error "无效选项" ;; esac done } deploy_certbot() { print_step "使用 Certbot 部署SSL证书..." # 安装certbot case $OS in ubuntu|debian) apt-get install -y certbot python3-certbot-nginx ;; centos|rhel) yum install -y certbot python3-certbot-nginx ;; esac # 申请证书 certbot --nginx -d "$DOMAIN" --non-interactive --agree-tos --email "admin@${DOMAIN}" --redirect # 配置自动续期 systemctl enable certbot.timer print_success "Certbot SSL证书部署成功" return 0 } deploy_acme_letsencrypt() { print_step "使用 acme.sh + Let's Encrypt 部署SSL证书..." # 安装acme.sh if [[ ! -d ~/.acme.sh ]]; then curl https://get.acme.sh | sh fi # 申请证书 ~/.acme.sh/acme.sh --issue -d "$DOMAIN" --nginx # 安装证书 mkdir -p /etc/nginx/ssl ~/.acme.sh/acme.sh --install-cert -d "$DOMAIN" \ --key-file /etc/nginx/ssl/${DOMAIN}.key \ --fullchain-file /etc/nginx/ssl/${DOMAIN}.crt \ --reloadcmd "systemctl reload nginx" print_success "acme.sh SSL证书部署成功" return 0 } deploy_acme_zerossl() { print_step "使用 acme.sh + ZeroSSL 部署SSL证书..." # 安装acme.sh if [[ ! -d ~/.acme.sh ]]; then curl https://get.acme.sh | sh fi # 申请证书 ~/.acme.sh/acme.sh --server zerossl --issue -d "$DOMAIN" --nginx # 安装证书 mkdir -p /etc/nginx/ssl ~/.acme.sh/acme.sh --install-cert -d "$DOMAIN" \ --key-file /etc/nginx/ssl/${DOMAIN}.key \ --fullchain-file /etc/nginx/ssl/${DOMAIN}.crt \ --reloadcmd "systemctl reload nginx" print_success "ZeroSSL证书部署成功" return 0 } deploy_acme_buypass() { print_step "使用 acme.sh + Buypass 部署SSL证书..." # 安装acme.sh if [[ ! -d ~/.acme.sh ]]; then curl https://get.acme.sh | sh fi # 申请证书 ~/.acme.sh/acme.sh --server buypass --issue -d "$DOMAIN" --nginx # 安装证书 mkdir -p /etc/nginx/ssl ~/.acme.sh/acme.sh --install-cert -d "$DOMAIN" \ --key-file /etc/nginx/ssl/${DOMAIN}.key \ --fullchain-file /etc/nginx/ssl/${DOMAIN}.crt \ --reloadcmd "systemctl reload nginx" print_success "Buypass SSL证书部署成功" return 0 } deploy_aliyun_ssl() { print_step "使用阿里云免费证书..." print_warning "此功能需要您提供阿里云AccessKey" echo "" read -p "阿里云AccessKey ID: " ALIYUN_ACCESS_KEY_ID read -p "阿里云AccessKey Secret: " ALIYUN_ACCESS_KEY_SECRET # 这里需要调用阿里云API申请证书 # 暂时返回失败,提示用户使用其他方案 print_error "阿里云证书申请功能开发中,请选择其他方案" return 1 } deploy_tencent_ssl() { print_step "使用腾讯云免费证书..." print_warning "此功能需要您提供腾讯云SecretKey" echo "" read -p "腾讯云SecretId: " TENCENT_SECRET_ID read -p "腾讯云SecretKey: " TENCENT_SECRET_KEY # 这里需要调用腾讯云API申请证书 # 暂时返回失败,提示用户使用其他方案 print_error "腾讯云证书申请功能开发中,请选择其他方案" return 1 } deploy_manual_ssl() { print_step "使用已有证书..." echo "" print_info "请将以下文件上传到服务器:" print_info "- 证书文件: /tmp/ssl_cert.crt" print_info "- 私钥文件: /tmp/ssl_key.key" echo "" read -p "上传完成后按回车继续..." if [[ -f /tmp/ssl_cert.crt ]] && [[ -f /tmp/ssl_key.key ]]; then mkdir -p /etc/nginx/ssl cp /tmp/ssl_cert.crt /etc/nginx/ssl/${DOMAIN}.crt cp /tmp/ssl_key.key /etc/nginx/ssl/${DOMAIN}.key chmod 600 /etc/nginx/ssl/${DOMAIN}.key print_success "证书文件已复制" return 0 else print_error "证书文件未找到" return 1 fi } ################################################################################ # 项目部署 ################################################################################ create_project_directory() { print_step "创建项目目录..." if [[ -d "$PROJECT_DIR" ]]; then print_warning "项目目录已存在" read -p "是否删除并重新创建? (y/n): " recreate if [[ "$recreate" == "y" || "$recreate" == "Y" ]]; then rm -rf "$PROJECT_DIR" else print_error "部署已取消" exit 1 fi fi mkdir -p "$PROJECT_DIR" print_success "项目目录已创建: $PROJECT_DIR" echo "" } download_project() { print_step "正在从Gitee下载项目..." cd /tmp if [[ -d "${PROJECT_NAME}" ]]; then rm -rf "${PROJECT_NAME}" fi git clone "$REPO_URL" "${PROJECT_NAME}" # 复制文件到项目目录 cp -r "/tmp/${PROJECT_NAME}"/* "$PROJECT_DIR/" # 清理临时文件 rm -rf "/tmp/${PROJECT_NAME}" print_success "项目下载完成" echo "" } configure_admin_account() { print_step "配置管理员账号" echo "" while true; do read -p "管理员用户名 [默认: admin]: " ADMIN_USERNAME ADMIN_USERNAME=${ADMIN_USERNAME:-admin} if [[ ${#ADMIN_USERNAME} -lt 3 ]]; then print_error "用户名至少3个字符" continue fi break done while true; do read -s -p "管理员密码(至少6位): " ADMIN_PASSWORD echo "" if [[ ${#ADMIN_PASSWORD} -lt 6 ]]; then print_error "密码至少6个字符" continue fi read -s -p "确认密码: " ADMIN_PASSWORD_CONFIRM echo "" if [[ "$ADMIN_PASSWORD" != "$ADMIN_PASSWORD_CONFIRM" ]]; then print_error "两次密码不一致" continue fi break done print_success "管理员账号配置完成" echo "" } install_backend_dependencies() { print_step "安装后端依赖..." cd "${PROJECT_DIR}/backend" # 使用国内镜像加速 if [[ "$USE_ALIYUN_MIRROR" == "true" ]]; then npm config set registry https://registry.npmmirror.com fi npm install --production print_success "后端依赖安装完成" echo "" } create_env_file() { print_step "创建配置文件..." # 生成随机JWT密钥 JWT_SECRET=$(openssl rand -base64 32) cat > "${PROJECT_DIR}/backend/.env" << EOF # 管理员账号 ADMIN_USERNAME=${ADMIN_USERNAME} ADMIN_PASSWORD=${ADMIN_PASSWORD} # JWT密钥 JWT_SECRET=${JWT_SECRET} # 数据库路径 DATABASE_PATH=./data/database.db # 存储目录 STORAGE_ROOT=./storage # 服务端口 PORT=40001 # 环境 NODE_ENV=production EOF print_success "配置文件创建完成" echo "" } create_data_directories() { print_step "创建数据目录..." mkdir -p "${PROJECT_DIR}/backend/data" mkdir -p "${PROJECT_DIR}/backend/storage" print_success "数据目录创建完成" echo "" } configure_nginx() { print_step "配置Nginx..." if [[ "$USE_DOMAIN" == "true" ]]; then if [[ "$SSL_METHOD" == "8" ]]; then # HTTP配置 configure_nginx_http else # HTTPS配置 configure_nginx_https fi else # IP模式HTTP配置 configure_nginx_http fi # 测试nginx配置 nginx -t # 重启nginx systemctl restart nginx print_success "Nginx配置完成" echo "" } configure_nginx_http() { local server_name="${DOMAIN:-_}" cat > /etc/nginx/sites-available/${PROJECT_NAME}.conf << EOF server { listen 80; server_name ${server_name}; # 前端静态文件 location / { root ${PROJECT_DIR}/frontend; index app.html; try_files \$uri \$uri/ /app.html; } # 后端API location /api { proxy_pass http://localhost:40001; proxy_http_version 1.1; proxy_set_header Upgrade \$http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host \$host; proxy_cache_bypass \$http_upgrade; 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; } # 分享页面 location /s { alias ${PROJECT_DIR}/frontend; try_files /share.html =404; } # 静态资源 location /libs { alias ${PROJECT_DIR}/frontend/libs; expires 30d; } # 上传工具下载 location /download-tool { alias ${PROJECT_DIR}/upload-tool/dist; } } EOF # 创建软链接 ln -sf /etc/nginx/sites-available/${PROJECT_NAME}.conf /etc/nginx/sites-enabled/${PROJECT_NAME}.conf # 删除默认站点 rm -f /etc/nginx/sites-enabled/default } configure_nginx_https() { cat > /etc/nginx/sites-available/${PROJECT_NAME}.conf << EOF server { listen 80; server_name ${DOMAIN}; return 301 https://\$server_name\$request_uri; } server { listen 443 ssl http2; server_name ${DOMAIN}; ssl_certificate /etc/nginx/ssl/${DOMAIN}.crt; ssl_certificate_key /etc/nginx/ssl/${DOMAIN}.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; # 前端静态文件 location / { root ${PROJECT_DIR}/frontend; index app.html; try_files \$uri \$uri/ /app.html; } # 后端API location /api { proxy_pass http://localhost:40001; proxy_http_version 1.1; proxy_set_header Upgrade \$http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host \$host; proxy_cache_bypass \$http_upgrade; 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; } # 分享页面 location /s { alias ${PROJECT_DIR}/frontend; try_files /share.html =404; } # 静态资源 location /libs { alias ${PROJECT_DIR}/frontend/libs; expires 30d; } # 上传工具下载 location /download-tool { alias ${PROJECT_DIR}/upload-tool/dist; } } EOF # 创建软链接 ln -sf /etc/nginx/sites-available/${PROJECT_NAME}.conf /etc/nginx/sites-enabled/${PROJECT_NAME}.conf # 删除默认站点 rm -f /etc/nginx/sites-enabled/default } start_backend_service() { print_step "启动后端服务..." cd "${PROJECT_DIR}/backend" # 使用PM2启动 pm2 start server.js --name ${PROJECT_NAME}-backend pm2 save print_success "后端服务已启动" echo "" } ################################################################################ # 健康检查 ################################################################################ health_check() { print_step "正在进行健康检查..." sleep 3 # 检查后端服务 if pm2 status | grep -q "${PROJECT_NAME}-backend.*online"; then print_success "后端服务运行正常" else print_error "后端服务启动失败" print_info "查看日志: pm2 logs ${PROJECT_NAME}-backend" return 1 fi # 检查端口 if netstat -tunlp | grep -q ":40001"; then print_success "后端端口监听正常 (40001)" else print_error "后端端口监听异常" return 1 fi # 检查Nginx if systemctl is-active --quiet nginx; then print_success "Nginx服务运行正常" else print_error "Nginx服务异常" return 1 fi # 检查数据库 if [[ -f "${PROJECT_DIR}/backend/data/database.db" ]]; then print_success "数据库初始化成功" else print_warning "数据库文件不存在" fi # 检查存储目录 if [[ -d "${PROJECT_DIR}/backend/storage" ]]; then print_success "文件存储目录就绪" else print_warning "存储目录不存在" fi echo "" return 0 } ################################################################################ # 完成提示 ################################################################################ print_completion() { clear echo -e "${GREEN}" echo "╔═══════════════════════════════════════════════════════════════╗" echo "║ ║" echo "║ 🎉 部署成功! ║" echo "║ ║" echo "╚═══════════════════════════════════════════════════════════════╝" echo -e "${NC}" echo "" # 访问地址 if [[ "$USE_DOMAIN" == "true" ]]; then if [[ "$SSL_METHOD" == "8" ]]; then echo -e "${CYAN}访问地址:${NC} http://${DOMAIN}" else echo -e "${CYAN}访问地址:${NC} https://${DOMAIN}" fi else PUBLIC_IP=$(curl -s ifconfig.me || curl -s icanhazip.com || echo "服务器IP") echo -e "${CYAN}访问地址:${NC} http://${PUBLIC_IP}" fi echo -e "${CYAN}管理员账号:${NC} ${ADMIN_USERNAME}" echo -e "${CYAN}管理员密码:${NC} ********" echo "" # 常用命令 echo -e "${YELLOW}常用命令:${NC}" echo " 查看服务状态: pm2 status" echo " 查看日志: pm2 logs ${PROJECT_NAME}-backend" echo " 重启服务: pm2 restart ${PROJECT_NAME}-backend" echo " 停止服务: pm2 stop ${PROJECT_NAME}-backend" echo "" # 配置文件位置 echo -e "${YELLOW}配置文件位置:${NC}" echo " 后端配置: ${PROJECT_DIR}/backend/.env" echo " Nginx配置: /etc/nginx/sites-enabled/${PROJECT_NAME}.conf" echo " 数据库: ${PROJECT_DIR}/backend/data/database.db" echo " 文件存储: ${PROJECT_DIR}/backend/storage" echo "" # SSL续期提示 if [[ "$USE_DOMAIN" == "true" ]] && [[ "$SSL_METHOD" != "8" ]]; then echo -e "${YELLOW}SSL证书:${NC}" case $SSL_METHOD in 1) echo " 自动续期: 已配置Certbot自动续期" ;; 2|3|4) echo " 自动续期: 已配置acme.sh自动续期" ;; esac echo "" fi echo -e "${GREEN}祝您使用愉快!${NC}" echo "" } ################################################################################ # 主流程 ################################################################################ main() { print_banner # 检查root权限 check_root # 系统检测 system_check # 选择软件源 choose_mirror # 安装依赖 install_dependencies # 选择访问模式 choose_access_mode # 配置管理员账号 configure_admin_account # 创建项目目录 create_project_directory # 下载项目 download_project # 安装后端依赖 install_backend_dependencies # 创建配置文件 create_env_file # 创建数据目录 create_data_directories # 部署SSL证书 deploy_ssl # 配置Nginx configure_nginx # 启动后端服务 start_backend_service # 健康检查 if ! health_check; then print_error "健康检查未通过,请检查日志" exit 1 fi # 完成提示 print_completion } # 执行主流程 main