diff --git a/install.sh b/install.sh index e9a8492..b8c047c 100644 --- a/install.sh +++ b/install.sh @@ -1,13 +1,18 @@ #!/bin/bash ################################################################################ -# 玩玩云 (WanWanYun) - 一键部署脚本 +# 玩玩云 (WanWanYun) - 一键部署/卸载脚本 # 项目地址: https://gitee.com/yu-yon/vue-driven-cloud-storage -# 版本: v1.1.2 +# 版本: v1.1.3 ################################################################################ set -e +# 检查运行模式 +MODE="install" +if [[ "$1" == "--uninstall" ]] || [[ "$1" == "-u" ]] || [[ "$1" == "uninstall" ]]; then + MODE="uninstall" +fi # 颜色定义 RED='\033[0;31m' @@ -1267,6 +1272,282 @@ print_completion() { echo "" } +################################################################################ +# 卸载功能 +################################################################################ + +print_uninstall_banner() { + clear + echo -e "${RED}" + echo "╔═══════════════════════════════════════════════════════════════╗" + echo "║ ║" + echo "║ ⚠️ 玩玩云 卸载模式 ║" + echo "║ ║" + echo "║ Uninstall Mode ║" + echo "║ ║" + echo "╚═══════════════════════════════════════════════════════════════╝" + echo -e "${NC}" +} + +confirm_uninstall() { + print_uninstall_banner + + echo -e "${YELLOW}" + echo "本脚本将执行以下操作:" + echo "" + echo "【将要删除】" + echo " ✓ PM2 进程: ${PROJECT_NAME}-backend" + echo " ✓ 项目目录: ${PROJECT_DIR}" + echo " ✓ Nginx 配置: /etc/nginx/sites-enabled/${PROJECT_NAME}.conf" + echo " ✓ 数据库文件: ${PROJECT_DIR}/backend/data/" + echo " ✓ 用户文件: ${PROJECT_DIR}/backend/storage/" + echo "" + echo "【将会保留】" + echo " ✓ Node.js" + echo " ✓ Nginx (程序本身)" + echo " ✓ PM2 (程序本身)" + echo " ✓ 编译工具 (build-essential等)" + echo -e "${NC}" + echo "" + + print_warning "此操作不可逆,所有数据将被永久删除!" + echo "" + + read -p "确定要卸载吗? (yes/no): " confirm < /dev/tty + + if [[ "$confirm" != "yes" ]]; then + print_info "已取消卸载" + exit 0 + fi + + echo "" + read -p "请再次确认 (yes/no): " confirm2 < /dev/tty + + if [[ "$confirm2" != "yes" ]]; then + print_info "已取消卸载" + exit 0 + fi + + echo "" +} + +uninstall_backup_data() { + print_step "备份用户数据..." + + if [[ ! -d "$PROJECT_DIR" ]]; then + print_info "项目目录不存在,跳过备份" + return + fi + + BACKUP_DIR="/root/${PROJECT_NAME}-backup-$(date +%Y%m%d-%H%M%S)" + + echo "" + read -p "是否备份用户数据? (y/n): " backup_choice < /dev/tty + + if [[ "$backup_choice" == "y" || "$backup_choice" == "Y" ]]; then + mkdir -p "$BACKUP_DIR" + + # 备份数据库 + if [[ -d "${PROJECT_DIR}/backend/data" ]]; then + cp -r "${PROJECT_DIR}/backend/data" "$BACKUP_DIR/" + print_success "数据库已备份" + fi + + # 备份用户文件 + if [[ -d "${PROJECT_DIR}/backend/storage" ]]; then + cp -r "${PROJECT_DIR}/backend/storage" "$BACKUP_DIR/" + print_success "用户文件已备份" + fi + + # 备份配置文件 + if [[ -f "${PROJECT_DIR}/backend/.env" ]]; then + cp "${PROJECT_DIR}/backend/.env" "$BACKUP_DIR/" + print_success "配置文件已备份" + fi + + print_success "备份已保存到: $BACKUP_DIR" + echo "" + else + print_warning "跳过备份,数据将被永久删除" + echo "" + fi +} + +uninstall_stop_pm2() { + print_step "停止PM2进程..." + + if command -v pm2 &> /dev/null; then + if pm2 list | grep -q "${PROJECT_NAME}-backend"; then + pm2 delete ${PROJECT_NAME}-backend + pm2 save --force + print_success "PM2进程已停止并删除" + else + print_info "PM2进程不存在,跳过" + fi + else + print_info "PM2未安装,跳过" + fi +} + +uninstall_nginx_config() { + print_step "删除Nginx配置..." + + local need_reload=false + + # 删除sites-enabled软链接 + if [[ -L /etc/nginx/sites-enabled/${PROJECT_NAME}.conf ]]; then + rm -f /etc/nginx/sites-enabled/${PROJECT_NAME}.conf + print_success "删除 sites-enabled 配置" + need_reload=true + fi + + # 删除sites-available配置文件 + if [[ -f /etc/nginx/sites-available/${PROJECT_NAME}.conf ]]; then + rm -f /etc/nginx/sites-available/${PROJECT_NAME}.conf + print_success "删除 sites-available 配置" + fi + + # 测试并重载nginx + if [[ "$need_reload" == true ]] && command -v nginx &> /dev/null; then + if nginx -t &> /dev/null; then + systemctl reload nginx + print_success "Nginx配置已重载" + else + print_warning "Nginx配置测试失败,请手动检查" + fi + fi +} + +uninstall_ssl_certificates() { + print_step "清理SSL证书..." + + # 删除nginx SSL证书目录下的项目证书 + local cert_removed=false + if [[ -d /etc/nginx/ssl ]]; then + # 使用find查找包含项目名或域名的证书 + find /etc/nginx/ssl -name "*${PROJECT_NAME}*" -type f -delete 2>/dev/null && cert_removed=true + fi + + if [[ "$cert_removed" == true ]]; then + print_success "已删除Nginx SSL证书" + else + print_info "未发现Nginx SSL证书" + fi + + # 提示acme.sh证书 + if [[ -d ~/.acme.sh ]]; then + if ~/.acme.sh/acme.sh --list 2>/dev/null | grep -q "Main_Domain"; then + print_info "检测到acme.sh证书" + print_warning "如需删除,请手动运行: ~/.acme.sh/acme.sh --remove -d " + fi + fi +} + +uninstall_project_directory() { + print_step "删除项目目录..." + + if [[ -d "$PROJECT_DIR" ]]; then + # 统计大小 + SIZE=$(du -sh "$PROJECT_DIR" 2>/dev/null | cut -f1 || echo "未知") + print_info "项目目录大小: $SIZE" + + # 删除目录 + rm -rf "$PROJECT_DIR" + print_success "项目目录已删除: $PROJECT_DIR" + else + print_info "项目目录不存在: $PROJECT_DIR" + fi +} + +uninstall_temp_files() { + print_step "清理临时文件..." + + local cleaned=false + + # 清理/tmp下的临时文件 + if [[ -d "/tmp/${PROJECT_NAME}" ]]; then + rm -rf "/tmp/${PROJECT_NAME}" + print_success "删除临时目录" + cleaned=true + fi + + # 清理npm缓存 + if command -v npm &> /dev/null; then + npm cache clean --force &> /dev/null || true + print_success "清理npm缓存" + cleaned=true + fi + + if [[ "$cleaned" == false ]]; then + print_info "无需清理" + fi +} + +uninstall_check_residual() { + print_step "检查残留文件..." + + local residual_found=false + + # 检查项目目录 + if [[ -d "$PROJECT_DIR" ]]; then + print_warning "残留: 项目目录 $PROJECT_DIR" + residual_found=true + fi + + # 检查Nginx配置 + if [[ -f /etc/nginx/sites-enabled/${PROJECT_NAME}.conf ]] || [[ -f /etc/nginx/sites-available/${PROJECT_NAME}.conf ]]; then + print_warning "残留: Nginx配置文件" + residual_found=true + fi + + # 检查PM2进程 + if command -v pm2 &> /dev/null; then + if pm2 list | grep -q "${PROJECT_NAME}"; then + print_warning "残留: PM2进程" + residual_found=true + fi + fi + + if [[ "$residual_found" == false ]]; then + print_success "未发现残留文件" + fi +} + +print_uninstall_completion() { + clear + echo -e "${GREEN}" + echo "╔═══════════════════════════════════════════════════════════════╗" + echo "║ ║" + echo "║ ✓ 卸载完成! ║" + echo "║ ║" + echo "╚═══════════════════════════════════════════════════════════════╝" + echo -e "${NC}" + echo "" + + echo -e "${CYAN}已删除内容:${NC}" + echo " ✓ PM2进程" + echo " ✓ 项目目录" + echo " ✓ Nginx配置" + echo " ✓ 数据库和用户文件" + echo "" + + echo -e "${CYAN}保留的环境:${NC}" + echo " ✓ Node.js $(node -v 2>/dev/null || echo '(未安装)')" + echo " ✓ Nginx $(nginx -v 2>&1 | cut -d'/' -f2 || echo '(未安装)')" + echo " ✓ PM2 $(pm2 -v 2>/dev/null || echo '(未安装)')" + echo " ✓ 编译工具 (build-essential 等)" + echo "" + + if [[ -n "$BACKUP_DIR" ]] && [[ -d "$BACKUP_DIR" ]]; then + echo -e "${YELLOW}备份位置:${NC}" + echo " $BACKUP_DIR" + echo "" + fi + + echo -e "${GREEN}感谢使用玩玩云!${NC}" + echo "" +} + ################################################################################ # 主流程 ################################################################################ @@ -1326,5 +1607,41 @@ main() { print_completion } +uninstall_main() { + # 检查root权限 + check_root + + # 确认卸载 + confirm_uninstall + + # 备份数据 + uninstall_backup_data + + # 停止PM2进程 + uninstall_stop_pm2 + + # 删除Nginx配置 + uninstall_nginx_config + + # 清理SSL证书 + uninstall_ssl_certificates + + # 删除项目目录 + uninstall_project_directory + + # 清理临时文件 + uninstall_temp_files + + # 检查残留 + uninstall_check_residual + + # 完成提示 + print_uninstall_completion +} + # 执行主流程 -main +if [[ "$MODE" == "uninstall" ]]; then + uninstall_main +else + main +fi