#!/bin/bash # 答题红包APP - 服务管理脚本 # 用于快速管理和监控部署的服务 set -e # 颜色定义 GREEN='\033[0;32m' YELLOW='\033[1;33m' RED='\033[0;31m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # 日志函数 log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } log_action() { echo -e "${CYAN}[ACTION]${NC} $1"; } # 显示菜单 show_menu() { clear echo "================================================" echo " 答题红包APP - 服务管理控制台" echo "================================================" echo echo "请选择要执行的操作:" echo echo "1. 应用管理" echo "2. 数据库管理" echo "3. 缓存管理" echo "4. Web服务器管理" echo "5. 系统监控" echo "6. 日志查看" echo "7. 备份和恢复" echo "8. 一键健康检查" echo "9. 更新和升级" echo "0. 退出" echo read -p "请输入选项 [0-9]: " OPTION echo } # 应用管理菜单 app_management() { clear echo "=== 应用管理 ===" echo echo "1. 查看PM2状态" echo "2. 重启API服务" echo "3. 停止API服务" echo "4. 启动API服务" echo "5. 查看应用日志" echo "6. 查看错误日志" echo "7. 监控应用性能" echo "8. 返回主菜单" echo read -p "请选择 [1-8]: " APP_OPTION case $APP_OPTION in 1) log_action "查看PM2状态..." pm2 status ;; 2) log_action "重启API服务..." pm2 restart question-redpacket-api pm2 save ;; 3) log_action "停止API服务..." pm2 stop question-redpacket-api ;; 4) log_action "启动API服务..." pm2 start question-redpacket-api pm2 save ;; 5) log_action "查看应用日志..." pm2 logs question-redpacket-api --lines 50 ;; 6) log_action "查看错误日志..." pm2 logs question-redpacket-api --err --lines 50 ;; 7) log_action "监控应用性能..." pm2 monit ;; 8) return ;; *) log_error "无效选项" ;; esac read -p "按 Enter 键继续..." app_management } # 数据库管理 database_management() { clear echo "=== 数据库管理 ===" echo echo "1. 连接MySQL数据库" echo "2. 查看数据库状态" echo "3. 备份数据库" echo "4. 恢复数据库" echo "5. 优化数据库" echo "6. 查看慢查询" echo "7. 返回主菜单" echo read -p "请选择 [1-7]: " DB_OPTION case $DB_OPTION in 1) log_action "连接MySQL数据库..." read -p "请输入数据库名称 [question_redpacket]: " DB_NAME DB_NAME=${DB_NAME:-question_redpacket} mysql -u root -p $DB_NAME ;; 2) log_action "查看数据库状态..." mysql -u root -p -e "SHOW DATABASES;" mysql -u root -p -e "SHOW PROCESSLIST;" ;; 3) log_action "备份数据库..." read -p "请输入备份文件名 [backup_$(date +%Y%m%d).sql]: " BACKUP_FILE BACKUP_FILE=${BACKUP_FILE:-backup_$(date +%Y%m%d).sql} mysqldump -u root -p question_redpacket > /tmp/$BACKUP_FILE log_success "数据库已备份到: /tmp/$BACKUP_FILE" ;; 4) log_action "恢复数据库..." echo "可用的备份文件:" ls -la /tmp/backup_*.sql 2>/dev/null || echo "无备份文件" read -p "请输入备份文件路径: " RESTORE_FILE if [ -f "$RESTORE_FILE" ]; then mysql -u root -p question_redpacket < $RESTORE_FILE log_success "数据库恢复完成" else log_error "备份文件不存在: $RESTORE_FILE" fi ;; 5) log_action "优化数据库..." mysql -u root -p -e "OPTIMIZE TABLE users, questions, answers, redpackets, withdrawals;" question_redpacket log_success "数据库优化完成" ;; 6) log_action "查看慢查询..." mysql -u root -p -e "SHOW VARIABLES LIKE 'slow_query_log';" mysql -u root -p -e "SHOW VARIABLES LIKE 'long_query_time';" echo "慢查询日志文件:" mysql -u root -p -e "SHOW VARIABLES LIKE 'slow_query_log_file';" ;; 7) return ;; *) log_error "无效选项" ;; esac read -p "按 Enter 键继续..." database_management } # 缓存管理 cache_management() { clear echo "=== Redis缓存管理 ===" echo echo "1. 连接Redis" echo "2. 查看Redis信息" echo "3. 清理Redis缓存" echo "4. 监控Redis性能" echo "5. 返回主菜单" echo read -p "请选择 [1-5]: " CACHE_OPTION case $CACHE_OPTION in 1) log_action "连接Redis..." redis-cli ;; 2) log_action "查看Redis信息..." redis-cli INFO | head -50 echo "..." redis-cli INFO memory redis-cli INFO stats ;; 3) log_action "清理Redis缓存..." read -p "确认清理所有缓存? (y/n): " CONFIRM if [[ $CONFIRM == "y" ]]; then redis-cli FLUSHALL log_success "Redis缓存已清理" fi ;; 4) log_action "监控Redis性能..." redis-cli MONITOR | head -100 ;; 5) return ;; *) log_error "无效选项" ;; esac read -p "按 Enter 键继续..." cache_management } # Web服务器管理 webserver_management() { clear echo "=== Nginx管理 ===" echo echo "1. 检查Nginx配置" echo "2. 重启Nginx" echo "3. 重新加载配置" echo "4. 停止Nginx" echo "5. 启动Nginx" echo "6. 查看Nginx状态" echo "7. 查看访问日志" echo "8. 查看错误日志" echo "9. 返回主菜单" echo read -p "请选择 [1-9]: " NGINX_OPTION case $NGINX_OPTION in 1) log_action "检查Nginx配置..." nginx -t ;; 2) log_action "重启Nginx..." systemctl restart nginx log_success "Nginx已重启" ;; 3) log_action "重新加载Nginx配置..." systemctl reload nginx log_success "Nginx配置已重载" ;; 4) log_action "停止Nginx..." systemctl stop nginx log_success "Nginx已停止" ;; 5) log_action "启动Nginx..." systemctl start nginx log_success "Nginx已启动" ;; 6) log_action "查看Nginx状态..." systemctl status nginx ;; 7) log_action "查看访问日志..." tail -f /var/log/nginx/question-redpacket-access.log ;; 8) log_action "查看错误日志..." tail -f /var/log/nginx/question-redpacket-error.log ;; 9) return ;; *) log_error "无效选项" ;; esac read -p "按 Enter 键继续..." webserver_management } # 系统监控 system_monitoring() { clear echo "=== 系统监控 ===" echo echo "1. 查看系统资源" echo "2. 查看磁盘使用" echo "3. 查看网络连接" echo "4. 查看进程列表" echo "5. 查看服务状态" echo "6. 查看系统日志" echo "7. 实时监控" echo "8. 返回主菜单" echo read -p "请选择 [1-8]: " MONITOR_OPTION case $MONITOR_OPTION in 1) log_action "查看系统资源..." top -bn1 | head -20 echo free -h ;; 2) log_action "查看磁盘使用..." df -h echo du -sh /var/www/question-redpacket/ ;; 3) log_action "查看网络连接..." netstat -tulpn | head -30 echo ss -tulpn | head -30 ;; 4) log_action "查看进程列表..." ps aux --sort=-%cpu | head -20 echo ps aux --sort=-%mem | head -20 ;; 5) log_action "查看服务状态..." echo "Nginx: $(systemctl is-active nginx)" echo "MySQL: $(systemctl is-active mysql || systemctl is-active mysqld)" echo "Redis: $(systemctl is-active redis || systemctl is-active redis-server)" echo "PM2: $(pm2 status | grep -q "online" && echo "运行中" || echo "停止")" ;; 6) log_action "查看系统日志..." journalctl -xe --no-pager | tail -50 ;; 7) log_action "启动实时监控..." htop ;; 8) return ;; *) log_error "无效选项" ;; esac read -p "按 Enter 键继续..." system_monitoring } # 日志查看 log_viewer() { clear echo "=== 日志查看器 ===" echo echo "1. 查看应用日志" echo "2. 查看错误日志" echo "3. 查看Nginx日志" echo "4. 查看MySQL日志" echo "5. 查看系统日志" echo "6. 实时日志跟踪" echo "7. 清理旧日志" echo "8. 返回主菜单" echo read -p "请选择 [1-8]: " LOG_OPTION APP_DIR="/var/www/question-redpacket/api-server" case $LOG_OPTION in 1) log_action "查看应用日志..." tail -100 $APP_DIR/logs/app.log ;; 2) log_action "查看错误日志..." tail -100 $APP_DIR/logs/error.log ;; 3) log_action "查看Nginx日志..." echo "访问日志:" tail -50 /var/log/nginx/access.log echo echo "错误日志:" tail -50 /var/log/nginx/error.log ;; 4) log_action "查看MySQL日志..." if [ -f "/var/log/mysql/error.log" ]; then tail -50 /var/log/mysql/error.log elif [ -f "/var/log/mysqld.log" ]; then tail -50 /var/log/mysqld.log else log_error "MySQL日志文件未找到" fi ;; 5) log_action "查看系统日志..." tail -50 /var/log/syslog ;; 6) log_action "实时日志跟踪..." echo "选择要跟踪的日志:" echo "1. 应用日志" echo "2. Nginx访问日志" echo "3. Nginx错误日志" echo "4. 系统日志" read -p "请选择 [1-4]: " TAIL_OPTION case $TAIL_OPTION in 1) tail -f $APP_DIR/logs/app.log ;; 2) tail -f /var/log/nginx/access.log ;; 3) tail -f /var/log/nginx/error.log ;; 4) tail -f /var/log/syslog ;; *) log_error "无效选项" ;; esac ;; 7) log_action "清理旧日志..." read -p "清理几天前的日志? [30]: " DAYS DAYS=${DAYS:-30} # 清理应用日志 find $APP_DIR/logs -name "*.log" -mtime +$DAYS -delete # 清理PM2日志 find /root/.pm2/logs -name "*.log" -mtime +$DAYS -delete # 清理Nginx日志 find /var/log/nginx -name "*.log" -mtime +$DAYS -delete log_success "已清理 $DAYS 天前的日志" ;; 8) return ;; *) log_error "无效选项" ;; esac read -p "按 Enter 键继续..." log_viewer } # 备份和恢复 backup_restore() { clear echo "=== 备份和恢复 ===" echo echo "1. 创建完整备份" echo "2. 恢复备份" echo "3. 列出备份文件" echo "4. 自动备份设置" echo "5. 返回主菜单" echo read -p "请选择 [1-5]: " BACKUP_OPTION BACKUP_DIR="/var/backups/question-redpacket" mkdir -p $BACKUP_DIR case $BACKUP_OPTION in 1) log_action "创建完整备份..." TIMESTAMP=$(date +%Y%m%d_%H%M%S) BACKUP_FILE="$BACKUP_DIR/full_backup_$TIMESTAMP.tar.gz" # 备份数据库 mysqldump -u root -p question_redpacket > /tmp/db_backup.sql # 备份应用代码和配置 tar -czf $BACKUP_FILE \ /var/www/question-redpacket \ /etc/nginx/sites-available/question-redpacket \ /etc/nginx/conf.d/question-redpacket.conf \ /tmp/db_backup.sql \ /root/.pm2 \ /etc/nginx/ssl/question-redpacket 2>/dev/null # 清理临时文件 rm -f /tmp/db_backup.sql log_success "完整备份已创建: $BACKUP_FILE" ls -lh $BACKUP_FILE ;; 2) log_action "恢复备份..." echo "可用备份:" ls -la $BACKUP_DIR/*.tar.gz 2>/dev/null || echo "无备份文件" read -p "请输入备份文件路径: " RESTORE_FILE if [ -f "$RESTORE_FILE" ]; then log_warning "这将覆盖现有数据!" read -p "确认恢复? (y/n): " CONFIRM if [[ $CONFIRM == "y" ]]; then # 停止服务 pm2 stop question-redpacket-api systemctl stop nginx # 提取备份 tar -xzf $RESTORE_FILE -C / # 恢复数据库 if [ -f "/tmp/db_backup.sql" ]; then mysql -u root -p question_redpacket < /tmp/db_backup.sql rm -f /tmp/db_backup.sql fi # 重启服务 pm2 start question-redpacket-api systemctl start nginx log_success "备份恢复完成" fi else log_error "备份文件不存在: $RESTORE_FILE" fi ;; 3) log_action "列出备份文件..." ls -la $BACKUP_DIR/ 2>/dev/null || echo "备份目录为空" echo du -sh $BACKUP_DIR/* 2>/dev/null || true ;; 4) log_action "自动备份设置..." echo "当前定时任务:" crontab -l | grep -E "(backup|rsync|tar)" echo echo "1. 设置每日备份" echo "2. 设置每周备份" echo "3. 删除备份任务" read -p "请选择 [1-3]: " CRON_OPTION case $CRON_OPTION in 1) # 每天凌晨2点备份 (crontab -l 2>/dev/null; echo "0 2 * * * $BACKUP_DIR/create_backup.sh") | crontab - log_success "已设置每日备份任务" ;; 2) # 每周日凌晨3点备份 (crontab -l 2>/dev/null; echo "0 3 * * 0 $BACKUP_DIR/create_backup.sh") | crontab - log_success "已设置每周备份任务" ;; 3) # 删除备份任务 crontab -l | grep -v "create_backup.sh" | crontab - log_success "已删除备份任务" ;; *) log_error "无效选项" ;; esac ;; 5) return ;; *) log_error "无效选项" ;; esac read -p "按 Enter 键继续..." backup_restore } # 一键健康检查 health_check() { clear echo "=== 一键健康检查 ===" echo log_action "开始系统健康检查..." echo "----------------------------------------" # 检查服务状态 log_info "1. 服务状态检查:" SERVICES=("nginx" "mysql" "mysqld" "redis" "redis-server") for SERVICE in "${SERVICES[@]}"; do if systemctl is-active $SERVICE >/dev/null 2>&1; then log_success " $SERVICE: ✓ 运行中" fi done # 检查PM2 if pm2 status | grep -q "online"; then log_success " PM2应用: ✓ 运行中" else log_error " PM2应用: ✗ 停止" fi # 检查端口 log_info "2. 端口检查:" PORTS=("80" "443" "3000" "3306" "6379") for PORT in "${PORTS[@]}"; do if netstat -tulpn | grep -q ":$PORT "; then log_success " 端口 $PORT: ✓ 监听中" else log_warning " 端口 $PORT: ✗ 未监听" fi done # 检查磁盘空间 log_info "3. 磁盘空间检查:" df -h / | tail -1 | awk '{if ($5 > 80) print " /: ✗ 使用率 " $5 " (超过80%)"; else print " /: ✓ 使用率 " $5}' df -h /var | tail -1 | awk '{if ($5 > 80) print " /var: ✗ 使用率 " $5 " (超过80%)"; else print " /var: ✓ 使用率 " $5}' # 检查内存使用 log_info "4. 内存使用检查:" free -h | awk 'NR==2{if ($3/$2 > 0.8) print " 内存: ✗ 使用率 " $3 "/" $2 " (超过80%)"; else print " 内存: ✓ 使用率 " $3 "/" $2}' # 检查API健康 log_info "5. API健康检查:" if curl -s http://localhost:3000/api/health | grep -q "ok"; then log_success " API服务: ✓ 健康" else log_error " API服务: ✗ 异常" fi # 检查数据库连接 log_info "6. 数据库连接检查:" if mysql -u root -p -e "SELECT 1;" >/dev/null 2>&1; then log_success " MySQL连接: ✓ 正常" else log_error " MySQL连接: ✗ 失败" fi # 检查Redis连接 log_info "7. Redis连接检查:" if redis-cli ping | grep -q "PONG"; then log_success " Redis连接: ✓ 正常" else log_error " Redis连接: ✗ 失败" fi echo "----------------------------------------" echo log_action "健康检查完成" read -p "按 Enter 键继续..." } # 更新和升级 update_system() { clear echo "=== 系统更新和升级 ===" echo echo "1. 更新系统包" echo "2. 更新Node.js应用" echo "3. 更新数据库迁移" echo "4. 清理无用包" echo "5. 查看更新日志" echo "6. 返回主菜单" echo read -p "请选择 [1-6]: " UPDATE_OPTION case $UPDATE_OPTION in 1) log_action "更新系统包..." if [ -f /etc/debian_version ]; then apt update && apt upgrade -y else yum update -y fi log_success "系统包更新完成" ;; 2) log_action "更新Node.js应用..." APP_DIR="/var/www/question-redpacket/api-server" cd $APP_DIR # 备份当前版本 git stash # 拉取最新代码 git pull origin main # 更新依赖 npm ci --only=production # 重启应用 pm2 restart question-redpacket-api log_success "Node.js应用更新完成" ;; 3) log_action "更新数据库迁移..." APP_DIR="/var/www/question-redpacket/api-server" cd $APP_DIR npx prisma generate npx prisma migrate deploy log_success "数据库迁移更新完成" ;; 4) log_action "清理无用包..." if [ -f /etc/debian_version ]; then apt autoremove -y apt clean else yum autoremove -y yum clean all fi log_success "系统清理完成" ;; 5) log_action "查看更新日志..." tail -50 /var/log/apt/history.log 2>/dev/null || echo "无更新日志" ;; 6) return ;; *) log_error "无效选项" ;; esac read -p "按 Enter 键继续..." update_system } # 主循环 main() { while true; do show_menu case $OPTION in 1) app_management ;; 2) database_management ;; 3) cache_management ;; 4) webserver_management ;; 5) system_monitoring ;; 6) log_viewer ;; 7) backup_restore ;; 8) health_check ;; 9) update_system ;; 0) echo "感谢使用,再见!" exit 0 ;; *) log_error "无效选项,请重新输入" read -p "按 Enter 键继续..." ;; esac done } # 执行主函数 main "$@"