🍎 本地Docker部署Gitea实战指南:打造专属Git服务器

272 阅读27分钟

🍎 本地Docker部署Gitea实战指南:打造专属Git服务器

🎯 前言

大家好,我是Leo哥。很久没有更新了,因为任务繁忙,博客,公众号都给耽搁,有不少读者问Leo哥是不是转行了,哈哈哈。最近也是忙里偷闲,正好上周有读者问到一些问题,今晚加班赶一篇出来。

🔄 缘由

上周有读者问到我,Leo哥,之前看过你公众号发过一篇关于云服务器自建Git客户端- Gitea的文章,mp.weixin.qq.com/s/_dXWBb_mI… 但是吧我还有有一些特殊的需求和问题,比如我的云服务器是白嫖的,如果到期了,我不想续费了,那我这个岂不是白白搭建了?一下数据岂不是全部没了。有没有更好的方案,比如部署到我自己的本地,这样我就只是自己使用,当做一个私有库来进行管理代码。这位朋友的疑问也很有道理,部署服务器虽然方便,但是迁移麻烦。所以今天Leo哥带来了一个本地化的方案。本文将详细记录在macOS系统上使用Docker部署Gitea的完整过程,特别关注与本地MySQL数据库的集成。(因为之前默认都是使用默认的SQLite3 数据库,这次我们把他放在本地MySQL进行管理。)

🛠️ 环境准备

📦 必备工具检查与配置

成功的项目总是从充分的准备开始。在我们开始部署之前,需要确保所有必要的工具都已经正确安装和配置。

Docker Desktop for Mac的验证与优化

注意: windows平台也是同理,本地没有安装docker的可先自行安装后再进行后续操作。

Docker Desktop是我们整个容器化策略的核心平台。它不仅提供了容器运行环境,还包含了许多便于开发的工具和功能。

# 验证Docker安装和版本
docker --version


# 检查Docker Compose的可用性
docker-compose --version


# 验证Docker服务状态
docker info | grep -E "(Server Version|Storage Driver)"


# 测试Docker基本功能
docker run hello-world

image-20250606214751566

image-20250606214751566

MySQL服务状态确认与配置检查

我们的项目依赖于一个已经运行的MySQL实例。这个数据库将作为Gitea的数据存储后端,承载用户账户、仓库元数据、权限设置等关键信息。

我们这次的数据等信息都需要依赖MySQL服务,大家在本地搭建一个MySQL环境即可,具体安装步骤这里就不过多赘述了。

默认情况下,MySQL可能只绑定到localhost接口,这意味着它只接受来自本机的连接。为了让Docker容器能够连接到MySQL,我们需要确保MySQL配置允许来自Docker网络的连接。

项目目录结构

自己可以在本地创建gitea后面安装的数据管理目录。

# 导航到用户主目录的项目区域
cd ~

# 创建Docker项目的根目录
mkdir -p docker-projects/gitea
cd docker-projects/gitea

# 验证当前位置
pwd

# 创建Gitea数据持久化目录
# 这个目录将成为所有重要数据的永久存储位置
mkdir -p gitea-data

# 创建配置管理目录
mkdir -p config


# 检查创建的目录结构
tree . || ls -la

🗄️ MySQL数据库配置

数据库相关设计

创建专用数据库实例

-- 创建Gitea专用数据库
-- 字符集选择体现了对国际化和现代应用需求的考虑
CREATE DATABASE gitea 
CHARACTER SET utf8mb4 
COLLATE utf8mb4_unicode_ci;

字符集的选择需要特别解释。utf8mb4是UTF-8编码的完整实现,它支持所有Unicode字符,包括emoji表情符号和各种特殊字符。这就像是选择一种能够表达所有人类语言的通用语言系统。在现代应用中,用户可能会在提交消息、仓库描述或用户名中使用emoji,utf8mb4确保了这些内容能够正确存储和显示。

utf8mb4_unicode_ci这个排序规则(collation)定义了字符比较和排序的方式。"ci"表示"case insensitive",意味着在比较字符串时不区分大小写。这为用户体验提供了便利,比如在搜索时不需要严格匹配大小写。

创建安全的用户账户体系

-- 创建Gitea服务专用用户
-- 分别为不同的连接场景创建用户实例
CREATE USER 'gitea'@'%' IDENTIFIED WITH mysql_native_password BY 'your password';
CREATE USER 'gitea'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your password';

这里我们创建了两个版本的gitea用户,这种设计体现了对网络连接复杂性的深刻理解。'%'通配符允许从任何主机连接,这对于Docker容器连接至关重要,因为容器的网络地址可能是动态的。'localhost'版本则为本地管理和测试提供了明确的访问路径。

mysql_native_password认证插件的选择也是经过深思熟虑的。虽然MySQL 8.0默认使用更安全的caching_sha2_password,但许多应用程序和客户端库还没有完全支持这种新的认证方式。选择mysql_native_password确保了最大的兼容性。

授予精确的权限范围

-- 为gitea用户分配数据库权限
-- 遵循最小权限原则,只授予必要的操作权限
GRANT ALL PRIVILEGES ON gitea.* TO 'gitea'@'%';
GRANT ALL PRIVILEGES ON gitea.* TO 'gitea'@'localhost';

-- 刷新权限系统,使更改立即生效
FLUSH PRIVILEGES;

权限授予的语法看起来简单,但其背后的安全理念很重要。gitea.*表示只对gitea数据库及其所有表授权,而不是整个MySQL实例。

验证配置的完整性

-- 检查用户创建情况
SELECT User, Host, plugin, account_locked, password_expired 
FROM mysql.user 
WHERE User = 'gitea';

-- 验证权限分配情况
SHOW GRANTS FOR 'gitea'@'%';
SHOW GRANTS FOR 'gitea'@'localhost';

-- 检查数据库创建情况
SHOW DATABASES LIKE 'gitea';

-- 退出MySQL控制台
EXIT;

连接性测试

以上步骤都没问题之后,尝试使用你创建的用户去本地进行连接数据库,然后创建一张表,进行crud操作,看看有没有权限等问题,如果都没问题,那么恭喜你已经完成了一半的步骤了。

🐳 Docker容器编排

Docker Compose配置

接下来创建一个完全适应你目录结构的Docker Compose文件。我这里在刚创建的目录下面。

image-20250606215710587

image-20250606215710587

cat > docker-compose.yml << 'EOF'
# Docker Compose配置文件
version: '3.8'

# 服务定义部分
# 在这个配置中,我们只定义一个服务(Gitea),因为MySQL已经在宿主机上运行
services:
  # Gitea服务配置
  gitea:
    # 使用官方Gitea镜像的最新版本
    image: gitea/gitea:latest
    
    # 为容器指定一个易于识别的名称
    container_name: gitea-app
    
    # 重启策略配置
    # "unless-stopped"意味着容器会在系统重启后自动启动,除非手动停止
    restart: unless-stopped
    
    # 环境变量配置部分
    # 这些变量告诉Gitea如何配置自己以及如何连接到外部服务
    environment:
      # 用户ID和组ID设置
      # 1000通常是macOS上第一个用户账户的ID
      USER_UID1000
      USER_GID1000
      
      # MySQL数据库连接配置
      # 这些设置告诉Gitea如何连接到你现有的MySQL服务
      GITEA__database__DB_TYPE: mysql
      # host.docker.internal是Docker在macOS上提供的特殊主机名
      # 它自动解析为宿主机的IP地址,从而允许容器访问宿主机服务
      GITEA__database__HOST: host.docker.internal:3306
      GITEA__database__NAME: gitea
      GITEA__database__USER: gitea
      # 确保这个密码与你在MySQL中设置的gitea用户密码完全匹配
      GITEA__database__PASSWD: your pasword
      # 字符集设置,确保支持完整的Unicode字符集,包括emoji
      GITEA__database__CHARSET: utf8mb4
      
      # 应用程序级别的配置
      # 这些设置影响Gitea的基本行为
      GITEA__server__DOMAIN: localhost
      GITEA__server__HTTP_PORT: 3000
      GITEA__server__ROOT_URL: http://localhost:3000/
      # 设置为生产模式以获得最佳性能和安全性
      GITEA__server__MODE: prod
      
    # 卷挂载配置
    # 这是数据持久化策略的核心部分
    volumes:
      # 将你的gitea-data目录挂载到容器的/data目录
      - /Users/leocoder/docker-projects/gitea/gitea-data:/data
      # 挂载系统时区信息,确保日志和时间戳显示正确
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    
    # 端口映射配置
    ports:
      # Web界面端口映射
      # 你可以通过 http://localhost:3000 访问Gitea
      - "3000:3000"
      # SSH服务端口映射
      # 将容器的22端口映射到宿主机的2222端口
      # 允许通过SSH克隆和推送Git仓库
      - "2222:22"
    
    # 主机名解析配置
    # 这确保容器能够正确解析宿主机地址
    extra_hosts:
      - "host.docker.internal:host-gateway"

EOF

🚀 服务部署

验证配置并启动服务

在启动服务之前,让我们验证配置文件的语法是否正确。

# 检查Docker Compose配置的语法
docker-compose config

# 如果配置正确,这个命令会显示解析后的完整配置
# 如果存在语法错误,它会提供具体的错误信息和行号

当你确认配置文件没有语法错误后,我们可以启动Gitea服务:

# 启动Gitea服务
# -d标志表示以守护进程模式运行(在后台运行)
docker-compose up -d

# 检查容器状态
docker-compose ps

# 查看服务启动日志
docker-compose logs -f gitea

⚙️ Gitea Web界面配置

页面访问

如果前面配置都没问题的话,直接访问: http://locaohost:3000/ 即可看到初始化页面。

让我们逐一验证这些预填充的值:

  • 数据库类型: MySQL ✅
  • 主机: host.docker.internal:3306 ✅
  • 数据库名称: gitea ✅
  • 用户名: gitea ✅
  • 密码: (已自动填充,显示为点号) ✅

image-20250606220544355

image-20250606220544355

SSH端口的重要修正

这是一个特别关键的配置项。默认显示的SSH端口是22,但我们需要将其修改为 2222。这个修改的重要性体现在:

我们的Docker容器虽然内部使用22端口,但通过端口映射暴露为宿主机的2222端口。当Gitea生成SSH克隆URL时,它需要知道外部访问的正确端口号。如果不修改这个设置,生成的URL会是:

ssh://git@localhost:22/username/repository.git  # 错误的端口

而正确的URL应该是:

ssh://git@localhost:2222/username/repository.git  # 正确的端口

这个细节的重要性不容忽视。

以上没问题的话就点击安装即可。然后进入页面进行注册用户,然后登录即可,这些我就不过多赘述了。

🧪 功能验证

成功登录Gitea后,我们需要进行一系列功能测试,确保所有核心功能都正常工作。这个过程就像是对新购买的复杂设备进行全面的功能检查,确保每个特性都按预期工作。

用户界面导航测试

首先,熟悉Gitea的用户界面布局和导航结构。主要区域包括:

image-20250606221113040

image-20250606221113040

  • 仪表板:显示最近活动和快速访问链接
  • 仓库管理:创建、查看和管理Git仓库
  • 组织管理:如果需要团队协作功能
  • 用户设置:个人配置和安全设置
  • 站点管理:系统级配置(仅管理员可见)

仓库创建与基础操作测试

image-20250606221234660

创建一个测试仓库来验证核心Git功能:

  1. 点击"+"按钮,选择"新建仓库"
  2. 设置仓库名称为"test-repository"
  3. 添加描述信息
  4. 选择初始化仓库并添加README文件
  5. 创建仓库并验证页面正确显示

image-20250606221336183

image-20250606221336183

这个界面是不是非常简介好看,解下来我们测试一下把本地的代码push过来测试一下效果,想必这些操作对于大家来说so easy吧,毕竟靠这个吃饭。

image-20250606222307671

可以看到已经成功提交到远程仓库了,大功告成。

文件操作功能验证

在测试仓库中进行基本的文件操作:

  • 编辑README文件
  • 创建新文件
  • 上传文件
  • 查看文件历史
  • 比较文件版本

🔐 SSH功能

SSH功能是Git日常使用的核心,我们需要彻底验证这个功能的可用性。

SSH密钥配置与管理

如果你还没有SSH密钥,需要先生成一对:

# 生成新的SSH密钥对
ssh-keygen -t ed25519 -C "your_email@example.com"

# 查看公钥内容
cat ~/.ssh/id_ed25519.pub

# 复制公钥内容,准备添加到Gitea

在Gitea的用户设置中添加SSH公钥:

  1. 进入用户设置 → SSH/GPG密钥
  2. 点击"增加密钥"
  3. 粘贴公钥内容
  4. 给密钥一个描述性名称
  5. 保存密钥

SSH连接测试与故障排除

# 测试SSH连接到Gitea
ssh -T git@localhost -p 2222

# 如果连接成功,你应该看到类似以下的消息:
# Hi username! You've successfully authenticated, but Gitea does not provide shell access.

# 如果连接失败,可以使用详细模式查看问题
ssh -T git@localhost -p 2222 -v

# 测试仓库克隆功能
git clone ssh://git@localhost:2222/你的用户名/test-repository.git

# 进入克隆的仓库目录
cd test-repository

# 验证远程仓库配置
git remote -v

SSH连接测试不仅验证了网络连接,还确认了身份验证机制正常工作。如果遇到连接问题,常见原因包括:

  • SSH密钥未正确添加到Gitea
  • 端口号错误(应该是2222而不是22)
  • 防火墙阻止连接
  • Docker网络配置问题

完整的Git工作流验证

# 在克隆的仓库中进行完整的Git操作测试
echo "# Test Content" >> test-file.md
git add test-file.md
git commit -m "Add test file via SSH"
git push origin master

# 验证推送是否成功
# 回到Gitea Web界面查看新提交是否出现

这个测试验证了完整的Git工作流,从本地修改到远程仓库同步,确保所有Git操作都正常工作,不过这都是些基本操作了。

🔄 备份与灾难恢复策略

自动化备份系统

#!/bin/bash
# 创建全面的备份脚本:backup-gitea.sh

# 设置备份目录和时间戳
BACKUP_DIR="/Users/$(whoami)/gitea-backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="gitea_backup_$TIMESTAMP"

# 创建备份目录
mkdir -p "$BACKUP_DIR"

# 停止Gitea服务以确保数据一致性
echo "🛑 停止Gitea服务..."
cd ~/docker-projects/gitea
docker-compose stop gitea

# 备份应用数据
echo "📦 备份应用数据..."
tar -czf "$BACKUP_DIR/${BACKUP_NAME}_data.tar.gz" \
    -C ~/docker-projects/gitea gitea-data/

# 备份MySQL数据
echo "🗄️ 备份数据库..."
mysqldump -u gitea -p'Gitea123!' \
    --single-transaction \
    --routines \
    --triggers \
    gitea > "$BACKUP_DIR/${BACKUP_NAME}_database.sql"

# 备份配置文件
echo "⚙️ 备份配置..."
cp docker-compose.yml "$BACKUP_DIR/${BACKUP_NAME}_docker-compose.yml"

# 重启服务
echo "🚀 重启Gitea服务..."
docker-compose start gitea

# 清理旧备份(保留最近7天)
find "$BACKUP_DIR" -name "gitea_backup_*" -mtime +7 -delete

echo "✅ 备份完成:$BACKUP_NAME"
echo "📍 备份位置:$BACKUP_DIR"

灾难恢复流程

#!/bin/bash
# 创建恢复脚本:restore-gitea.sh

BACKUP_DIR="/Users/$(whoami)/gitea-backups"
BACKUP_DATE=$1

if [ -z "$BACKUP_DATE" ]; then
    echo "使用方法: $0 <backup_date>"
    echo "可用备份:"
    ls -1 "$BACKUP_DIR" | grep "gitea_backup_" | cut -d'_' -f3-4
    exit 1
fi

BACKUP_NAME="gitea_backup_$BACKUP_DATE"

echo "🔄 开始恢复过程..."
cd ~/docker-projects/gitea

# 停止服务
docker-compose down

# 备份当前数据(以防恢复失败)
mv gitea-data "gitea-data.backup.$(date +%Y%m%d_%H%M%S)"

# 恢复应用数据
echo "📦 恢复应用数据..."
tar -xzf "$BACKUP_DIR/${BACKUP_NAME}_data.tar.gz"

# 恢复数据库
echo "🗄️ 恢复数据库..."
mysql -u root -p -e "DROP DATABASE IF EXISTS gitea;"
mysql -u root -p -e "CREATE DATABASE gitea CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql -u gitea -p'Gitea123!' gitea < "$BACKUP_DIR/${BACKUP_NAME}_database.sql"

# 恢复配置
cp "$BACKUP_DIR/${BACKUP_NAME}_docker-compose.yml" docker-compose.yml

# 重启服务
docker-compose up -d

echo "✅ 恢复完成"

📊 系统监控与维护

在成功部署Gitea服务之后,建立完善的监控与维护体系就像为一座精密的机器配备专业的维护团队。这不仅能确保服务的稳定运行,更能帮助我们及早发现问题、优化性能,并在关键时刻快速响应。让我们一步步构建一个真正实用的监控与维护体系。

🛠️ 核心监控组件实现

基础健康检查系统

基础健康检查是监控体系的基石,它需要快速、可靠、易于理解。我们的健康检查系统采用了多维度验证的方法,从不同角度确认系统的正常运行。

#!/bin/bash
# 企业级健康检查脚本 - health-check.sh
# 这个脚本提供快速、全面的系统状态概览

# 颜色定义 - 提升用户体验的重要细节
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 统一的状态输出函数 - 确保信息展示的一致性
print_status() {
    local status=$1
    local message=$2
    
    case $status in
        "OK"echo -e "${GREEN}✅ $message${NC}" ;;
        "WARNING"echo -e "${YELLOW}⚠️  $message${NC}" ;;
        "ERROR"echo -e "${RED}❌ $message${NC}" ;;
        "INFO"echo -e "${BLUE}ℹ️  $message${NC}" ;;
    esac
}

# Docker服务状态检查 - 容器化环境的基础验证
check_docker_service() {
    echo
    print_status "INFO" "检查Docker服务状态..."
    
    if docker info >/dev/null 2>&1; then
        print_status "OK" "Docker服务运行正常"
        
        # 获取Docker版本信息用于兼容性验证
        local docker_version=$(docker --version | grep -oE '[0-9]+.[0-9]+.[0-9]+')
        print_status "INFO" "Docker版本: $docker_version"
    else
        print_status "ERROR" "Docker服务未运行或无法访问"
        return 1
    fi
}

# Gitea容器状态检查 - 应用容器的健康验证
check_gitea_container() {
    echo
    print_status "INFO" "检查Gitea容器状态..."
    
    if docker ps | grep -q "gitea-app"then
        print_status "OK" "Gitea容器正在运行"
        
        # 检查容器的详细状态信息
        local container_status=$(docker inspect gitea-app --format='{{.State.Status}}')
        local uptime=$(docker inspect gitea-app --format='{{.State.StartedAt}}' | cut -d'T' -f1,2 | tr 'T' ' ')
        local restart_count=$(docker inspect gitea-app --format='{{.RestartCount}}')
        
        print_status "INFO" "容器状态: $container_status"
        print_status "INFO" "启动时间: $uptime"
        
        if [ "$restart_count" -eq 0 ]; then
            print_status "OK" "容器运行稳定(无重启记录)"
        else
            print_status "WARNING" "容器已重启 $restart_count 次"
        fi
    else
        print_status "ERROR" "Gitea容器未运行"
        return 1
    fi
}

# 网络连接性检查 - 关键服务端点的可达性验证
check_network_connectivity() {
    echo
    print_status "INFO" "检查网络连接性..."
    
    # HTTP服务检查 - Web界面的核心功能
    if curl -sf http://localhost:3000 >/dev/null 2>&1; then
        # 测量响应时间以评估性能
        local response_time=$(curl -o /dev/null -s -w '%{time_total}' http://localhost:3000 2>/dev/null)
        local response_ms=$(echo "$response_time * 1000" | bc 2>/dev/null)
        
        if (( $(echo "$response_time < 0.1" | bc -l 2>/dev/null || echo 0) )); then
            print_status "OK" "HTTP服务响应优秀 (${response_ms}ms)"
        elif (( $(echo "$response_time < 0.5" | bc -l 2>/dev/null || echo 0) )); then
            print_status "OK" "HTTP服务响应良好 (${response_ms}ms)"
        else
            print_status "WARNING" "HTTP服务响应较慢 (${response_ms}ms)"
        fi
    else
        print_status "ERROR" "HTTP服务不可达"
    fi
    
    # SSH服务检查 - Git操作的关键通道
    if nc -z localhost 2222 2>/dev/null; then
        print_status "OK" "SSH服务可达"
    else
        print_status "ERROR" "SSH服务不可达"
    fi
}

# 智能数据库连接检查 - 适应容器化环境的连接验证
check_database_connection() {
    echo
    print_status "INFO" "检查数据库连接状态..."
    
    # 通过Gitea应用的运行状态间接验证数据库连接
    # 这种方法避免了直接数据库连接可能遇到的网络和认证复杂性
    
    # 检查Gitea日志中是否有数据库相关错误
    local db_errors=$(docker-compose logs gitea --since 1h 2>/dev/null | grep -i "database.*error|mysql.*error" | wc -l)
    
    if [ "$db_errors" -eq 0 ]; then
        print_status "OK" "Gitea日志中无数据库错误"
    else
        print_status "WARNING" "发现 $db_errors 条数据库相关错误"
    fi
    
    # 通过API端点验证数据库集成功能
    if curl -sf http://localhost:3000/api/v1/version >/dev/null 2>&1; then
        print_status "OK" "API响应正常,数据库集成工作正常"
    else
        print_status "WARNING" "API端点无响应,可能存在数据库问题"
    fi
}

# 资源使用情况监控 - 系统性能和容量的关键指标
check_resource_usage() {
    echo
    print_status "INFO" "检查资源使用情况..."
    
    # 获取容器资源使用统计
    local stats=$(docker stats gitea-app --no-stream --format "{{.CPUPerc}},{{.MemUsage}},{{.MemPerc}}" 2>/dev/null)
    
    if [ -n "$stats" ]; then
        IFS=',' read -r cpu_usage mem_usage mem_percent <<< "$stats"
        
        # CPU使用率评估
        local cpu_num=$(echo "$cpu_usage" | sed 's/%//')
        if (( $(echo "$cpu_num < 20" | bc -l 2>/dev/null || echo 0) )); then
            print_status "OK" "CPU使用率正常: $cpu_usage"
        elif (( $(echo "$cpu_num < 50" | bc -l 2>/dev/null || echo 0) )); then
            print_status "WARNING" "CPU使用率偏高: $cpu_usage"
        else
            print_status "ERROR" "CPU使用率过高: $cpu_usage"
        fi
        
        # 内存使用率评估
        local mem_num=$(echo "$mem_percent" | sed 's/%//')
        if (( $(echo "$mem_num < 50" | bc -l 2>/dev/null || echo 0) )); then
            print_status "OK" "内存使用正常: $mem_usage ($mem_percent)"
        elif (( $(echo "$mem_num < 80" | bc -l 2>/dev/null || echo 0) )); then
            print_status "WARNING" "内存使用偏高: $mem_usage ($mem_percent)"
        else
            print_status "ERROR" "内存使用过高: $mem_usage ($mem_percent)"
        fi
    else
        print_status "ERROR" "无法获取容器资源统计"
    fi
    
    # 磁盘空间检查 - 数据存储的容量管理
    local disk_usage=$(df -h ~/docker-projects/gitea/gitea-data | tail -1 | awk '{print $5}' | sed 's/%//')
    local disk_avail=$(df -h ~/docker-projects/gitea/gitea-data | tail -1 | awk '{print $4}')
    
    if [ "$disk_usage" -lt 70 ]; then
        print_status "OK" "磁盘使用率正常: ${disk_usage}% (可用: $disk_avail)"
    elif [ "$disk_usage" -lt 85 ]; then
        print_status "WARNING" "磁盘使用率偏高: ${disk_usage}% (可用: $disk_avail)"
    else
        print_status "ERROR" "磁盘空间不足: ${disk_usage}% (可用: $disk_avail)"
    fi
}

# 主执行函数 - 协调所有检查项目的执行
main() {
    echo -e "${BLUE}🏥 Gitea系统健康检查 - $(date)${NC}"
    echo "=================================================="
    
    check_docker_service
    check_gitea_container
    check_network_connectivity
    check_database_connection
    check_resource_usage
    
    echo "=================================================="
    echo -e "${BLUE}🏁 健康检查完成 - $(date)${NC}"
}

# 执行主函数
main "$@"
智能活动监控系统

在基础健康检查的基础上,我们需要一个能够理解和分析Gitea实际运行模式的智能监控系统。这个系统不仅收集数据,更重要的是能够理解数据的含义并识别异常模式。

#!/bin/bash
# 智能活动监控系统 - intelligent-monitor.sh
# 深入分析Gitea的运行模式和性能特征

REPORT_DIR="$HOME/docker-projects/gitea/monitoring/reports"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)

# 创建必要的目录结构
mkdir -p "$REPORT_DIR"

# 分析系统活动模式 - 理解用户行为和系统负载
analyze_activity_patterns() {
    local timeframe="${1:-1h}"
    echo "📊 分析最近${timeframe}的活动模式..."
    
    # 获取指定时间范围内的日志
    local logs=$(docker-compose logs gitea --since "$timeframe" 2>/dev/null)
    
    if [ -z "$logs" ]; then
        echo "⚠️  无法获取日志数据"
        return 1
    fi
    
    # HTTP请求分析 - 了解用户访问模式
    local get_requests=$(echo "$logs" | grep -c "completed GET")
    local post_requests=$(echo "$logs" | grep -c "completed POST")
    local total_requests=$((get_requests + post_requests))
    
    echo "🌐 HTTP活动统计:"
    echo "   GET请求: $get_requests 次"
    echo "   POST请求: $post_requests 次"
    echo "   总请求数: $total_requests 次"
    
    # 响应时间分析 - 评估系统性能
    if [ "$get_requests" -gt 0 ]; then
        local avg_response=$(echo "$logs" | grep "completed GET" | \
            sed -n 's/.*in ([0-9.]*)ms.*/\1/p' | \
            awk '{sum+=$1; count++} END {if(count>0) printf "%.1f", sum/count; else print "0"}')
        
        echo "⚡ 性能指标:"
        echo "   平均响应时间: ${avg_response}ms"
        
        # 性能评估
        if (( $(echo "$avg_response < 5.0" | bc -l 2>/dev/null || echo 0) )); then
            echo "   性能评估: 优秀 ✅"
        elif (( $(echo "$avg_response < 20.0" | bc -l 2>/dev/null || echo 0) )); then
            echo "   性能评估: 良好 👍"
        else
            echo "   性能评估: 需要关注 ⚠️"
        fi
    fi
    
    # 监控频率检测 - 识别自动化监控模式
    local monitoring_pattern=$(echo "$logs" | grep "completed GET /" | wc -l)
    if [ "$monitoring_pattern" -gt 10 ]; then
        local frequency=$(echo "scale=1; $monitoring_pattern * 3600 / $(date -d '1 hour ago' +%s; date +%s | paste -sd- | bc)" | bc 2>/dev/null || echo "未知")
        echo "🔍 检测到规律性监控活动:"
        echo "   频率: 约每秒 $frequency 次"
        echo "   说明: 这通常表明有健康检查或监控探针在运行"
    fi
}

# 错误和异常分析 - 识别潜在问题
analyze_errors_and_anomalies() {
    local timeframe="${1:-24h}"
    echo
    echo "🚨 错误和异常分析 (最近${timeframe})..."
    
    # 错误日志统计
    local error_count=$(docker-compose logs gitea --since "$timeframe" 2>/dev/null | grep -i "error|fatal|panic" | wc -l)
    local warning_count=$(docker-compose logs gitea --since "$timeframe" 2>/dev/null | grep -i "warn" | wc -l)
    
    echo "📈 日志级别统计:"
    echo "   错误日志: $error_count 条"
    echo "   警告日志: $warning_count 条"
    
    if [ "$error_count" -eq 0 ] && [ "$warning_count" -eq 0 ]; then
        echo "   状态: 系统运行稳定 ✅"
    elif [ "$error_count" -eq 0 ] && [ "$warning_count" -lt 5 ]; then
        echo "   状态: 轻微警告,总体良好 👍"
    else
        echo "   状态: 需要关注 ⚠️"
        
        # 显示最近的错误示例
        if [ "$error_count" -gt 0 ]; then
            echo
            echo "🔍 最近的错误示例:"
            docker-compose logs gitea --since "$timeframe" 2>/dev/null | grep -i "error|fatal" | tail -3 | sed 's/^/   /'
        fi
    fi
}

# 生成综合性能报告 - 为管理层提供概览信息
generate_performance_report() {
    local report_file="$REPORT_DIR/performance_report_$TIMESTAMP.txt"
    
    echo "📄 生成综合性能报告..."
    
    {
        echo "Gitea系统性能报告"
        echo "生成时间: $(date)"
        echo "报告周期: 过去24小时"
        echo "========================================"
        echo
        
        echo "📊 系统概览:"
        docker stats gitea-app --no-stream --format \
        "   CPU使用率: {{.CPUPerc}}
   内存使用: {{.MemUsage}} ({{.MemPerc}})
   网络I/O: {{.NetIO}}
   磁盘I/O: {{.BlockIO}}"
        
        echo
        echo "🌐 服务可用性:"
        if curl -sf http://localhost:3000 >/dev/null 2>&1; then
            echo "   Web服务: 正常 ✅"
        else
            echo "   Web服务: 异常 ❌"
        fi
        
        if nc -z localhost 2222 2>/dev/null; then
            echo "   SSH服务: 正常 ✅"
        else
            echo "   SSH服务: 异常 ❌"
        fi
        
        echo
        echo "📈 活动统计 (24小时):"
        docker-compose logs gitea --since 24h 2>/dev/null | \
        awk '
        /completed GET/ { get_count++ }
        /completed POST/ { post_count++ }
        /error|ERROR/ { error_count++ }
        /warn|WARN/ { warn_count++ }
        END {
            print "   GET请求: " (get_count ? get_count : 0) " 次"
            print "   POST请求: " (post_count ? post_count : 0) " 次"
            print "   错误记录: " (error_count ? error_count : 0) " 条"
            print "   警告记录: " (warn_count ? warn_count : 0) " 条"
        }'
        
        echo
        echo "💾 存储状况:"
        df -h ~/docker-projects/gitea/gitea-data | tail -1 | \
        awk '{print "   磁盘使用: " $3 "/" $2 " (" $5 ")\n   可用空间: " $4}'
        
        echo
        echo "🐳 容器信息:"
        docker inspect gitea-app --format \
        "   镜像版本: {{.Config.Image}}
   启动时间: {{.State.StartedAt}}
   重启次数: {{.RestartCount}}
   运行状态: {{.State.Status}}"
        
    } > "$report_file"
    
    echo "✅ 报告已生成: $report_file"
    echo "📂 报告位置: $REPORT_DIR"
}

# 实时监控模式 - 提供动态的系统观察
real_time_monitoring() {
    echo "🔴 启动实时监控模式..."
    echo "监控Gitea活动,按Ctrl+C停止"
    echo "----------------------------------------"
    
    local request_count=0
    local error_count=0
    local start_time=$(date +%s)
    
    docker-compose logs -f gitea 2>/dev/null | while read -r line; do
        local timestamp=$(date '+%H:%M:%S')
        
        # 分类处理不同类型的日志
        if echo "$line" | grep -q "completed GET"then
            request_count=$((request_count + 1))
            
            # 提取响应时间并评估
            local response_time=$(echo "$line" | sed -n 's/.*in ([0-9.]*)ms.*/\1/p')
            if [ -n "$response_time" ] && (( $(echo "$response_time > 100" | bc -l 2>/dev/null || echo 0) )); then
                echo -e "\033[1;33m[$timestamp] 🐌 慢响应: ${response_time}ms\033[0m"
            fi
            
            # 定期显示统计信息
            if [ $((request_count % 50)) -eq 0 ]; then
                local current_time=$(date +%s)
                local duration=$((current_time - start_time))
                local rps=$(echo "scale=1; $request_count / $duration" | bc 2>/dev/null || echo "0")
                echo -e "\033[0;32m[$timestamp] 📊 统计: $request_count 请求, $rps RPS\033[0m"
            fi
            
        elif echo "$line" | grep -q "completed POST"then
            local endpoint=$(echo "$line" | sed -n 's/.*POST ([^ ]*).*/\1/p')
            echo -e "\033[0;34m[$timestamp] 📝 POST: $endpoint\033[0m"
            
        elif echo "$line" | grep -qi "error|fatal"then
            error_count=$((error_count + 1))
            echo -e "\033[0;31m[$timestamp] 🚨 错误 #$error_count$line\033[0m"
            
        elif echo "$line" | grep -qi "warn"then
            echo -e "\033[1;33m[$timestamp] ⚠️  警告: $line\033[0m"
        fi
    done
}

# 主函数 - 处理不同的操作模式
main() {
    case "${1:-status}" in
        "status")
            echo "🎯 Gitea智能监控系统 - $(date)"
            echo "=============================================="
            analyze_activity_patterns "1h"
            analyze_errors_and_anomalies "24h"
            ;;
        "report")
            generate_performance_report
            ;;
        "monitor")
            real_time_monitoring
            ;;
        "analyze")
            echo "🔍 深度分析模式"
            analyze_activity_patterns "6h"
            analyze_errors_and_anomalies "7d"
            ;;
        *)
            echo "使用方法: $0 [status|report|monitor|analyze]"
            echo "  status  - 显示当前系统状态"
            echo "  report  - 生成性能报告"
            echo "  monitor - 实时监控"
            echo "  analyze - 深度分析"
            ;;
    esac
}

main "$@"

📈 健康评分与趋势分析

量化健康评估系统

为了更直观地了解系统状态,我们需要建立一个量化的健康评分系统。这个系统就像体检报告中的各项指标,能够将复杂的系统状态转化为易于理解的数字评分。

#!/bin/bash
# 系统健康评分系统 - health-assessment.sh
# 提供量化的系统健康评估

# 健康评分计算函数
calculate_health_score() {
    local total_score=0
    local max_score=100
    local category_scores=""
    
    echo "🎯 Gitea系统健康评分"
    echo "==============================="
    
    # 服务可用性评分 (25分)
    echo "📊 服务可用性评估..."
    local availability_score=0
    
    if curl -sf http://localhost:3000 >/dev/null 2>&1; then
        availability_score=$((availability_score + 15))
        echo "   ✅ Web服务可达 (+15分)"
    else
        echo "   ❌ Web服务不可达 (0分)"
    fi
    
    if nc -z localhost 2222 2>/dev/null; then
        availability_score=$((availability_score + 10))
        echo "   ✅ SSH服务可达 (+10分)"
    else
        echo "   ❌ SSH服务不可达 (0分)"
    fi
    
    total_score=$((total_score + availability_score))
    category_scores="$category_scores 可用性:$availability_score/25"
    
    # 性能评分 (25分)
    echo
    echo "⚡ 性能评估..."
    local performance_score=0
    
    local response_time=$(curl -o /dev/null -s -w '%{time_total}' http://localhost:3000 2>/dev/null)
    if [ -n "$response_time" ]; then
        if (( $(echo "$response_time < 0.1" | bc -l) )); then
            performance_score=$((performance_score + 25))
            echo "   🚀 响应时间优秀: ${response_time}s (+25分)"
        elif (( $(echo "$response_time < 0.5" | bc -l) )); then
            performance_score=$((performance_score + 20))
            echo "   ✅ 响应时间良好: ${response_time}s (+20分)"
        elif (( $(echo "$response_time < 1.0" | bc -l) )); then
            performance_score=$((performance_score + 15))
            echo "   ⚠️  响应时间一般: ${response_time}s (+15分)"
        else
            performance_score=$((performance_score + 5))
            echo "   🐌 响应时间较慢: ${response_time}s (+5分)"
        fi
    fi
    
    total_score=$((total_score + performance_score))
    category_scores="$category_scores 性能:$performance_score/25"
    
    # 稳定性评分 (25分)
    echo
    echo "🔒 稳定性评估..."
    local stability_score=0
    
    local error_count=$(docker-compose logs gitea --since 24h 2>/dev/null | grep -i "error|fatal" | wc -l)
    local total_requests=$(docker-compose logs gitea --since 24h 2>/dev/null | grep "completed" | wc -l)
    
    if [ "$total_requests" -gt 0 ]; then
        local error_rate=$(echo "scale=4; $error_count * 100 / $total_requests" | bc)
        if (( $(echo "$error_rate == 0" | bc -l) )); then
            stability_score=$((stability_score + 25))
            echo "   🎯 零错误率 (+25分)"
        elif (( $(echo "$error_rate < 0.1" | bc -l) )); then
            stability_score=$((stability_score + 20))
            echo "   ✅ 低错误率: ${error_rate}% (+20分)"
        elif (( $(echo "$error_rate < 1.0" | bc -l) )); then
            stability_score=$((stability_score + 15))
            echo "   ⚠️  错误率: ${error_rate}% (+15分)"
        else
            stability_score=$((stability_score + 5))
            echo "   🚨 高错误率: ${error_rate}% (+5分)"
        fi
    else
        stability_score=$((stability_score + 20))
        echo "   ℹ️  无足够数据,给予基础分数 (+20分)"
    fi
    
    total_score=$((total_score + stability_score))
    category_scores="$category_scores 稳定性:$stability_score/25"
    
    # 资源效率评分 (25分)
    echo
    echo "💻 资源效率评估..."
    local efficiency_score=0
    
    local stats=$(docker stats gitea-app --no-stream --format "{{.CPUPerc}},{{.MemPerc}}" 2>/dev/null)
    if [ -n "$stats" ]; then
        IFS=',' read -r cpu_usage mem_usage <<< "$stats"
        local cpu_num=$(echo "$cpu_usage" | sed 's/%//')
        local mem_num=$(echo "$mem_usage" | sed 's/%//')
        
        # CPU效率评分
        if (( $(echo "$cpu_num < 10" | bc -l) )); then
            efficiency_score=$((efficiency_score + 15))
            echo "   ✅ CPU使用优秀: $cpu_usage (+15分)"
        elif (( $(echo "$cpu_num < 30" | bc -l) )); then
            efficiency_score=$((efficiency_score + 12))
            echo "   👍 CPU使用良好: $cpu_usage (+12分)"
        elif (( $(echo "$cpu_num < 70" | bc -l) )); then
            efficiency_score=$((efficiency_score + 8))
            echo "   ⚠️  CPU使用偏高: $cpu_usage (+8分)"
        else
            efficiency_score=$((efficiency_score + 3))
            echo "   🚨 CPU使用过高: $cpu_usage (+3分)"
        fi
        
        # 内存效率评分
        if (( $(echo "$mem_num < 20" | bc -l) )); then
            efficiency_score=$((efficiency_score + 10))
            echo "   ✅ 内存使用优秀: $mem_usage (+10分)"
        elif (( $(echo "$mem_num < 50" | bc -l) )); then
            efficiency_score=$((efficiency_score + 8))
            echo "   👍 内存使用良好: $mem_usage (+8分)"
        elif (( $(echo "$mem_num < 80" | bc -l) )); then
            efficiency_score=$((efficiency_score + 5))
            echo "   ⚠️  内存使用偏高: $mem_usage (+5分)"
        else
            efficiency_score=$((efficiency_score + 2))
            echo "   🚨 内存使用过高: $mem_usage (+2分)"
        fi
    fi
    
    total_score=$((total_score + efficiency_score))
    category_scores="$category_scores 效率:$efficiency_score/25"
    
    # 总结评分
    echo
    echo "==============================="
    echo "📊 详细评分: $category_scores"
    echo "🎯 总体健康评分: $total_score/$max_score"
    
    # 评级系统
    if [ "$total_score" -ge 90 ]; then
        echo "🏆 系统状态: 优秀 (A级)"
        echo "💡 建议: 继续保持当前的运维水平"
    elif [ "$total_score" -ge 80 ]; then
        echo "🥈 系统状态: 良好 (B级)"
        echo "💡 建议: 关注低分项目,持续优化"
    elif [ "$total_score" -ge 70 ]; then
        echo "🥉 系统状态: 合格 (C级)"
        echo "💡 建议: 需要重点关注和改进"
    elif [ "$total_score" -ge 60 ]; then
        echo "⚠️  系统状态: 需要关注 (D级)"
        echo "💡 建议: 立即开始改进措施"
    else
        echo "🚨 系统状态: 需要紧急处理 (F级)"
        echo "💡 建议: 立即进行全面检查和修复"
    fi
    
    # 将评分记录到历史文件
    local score_file="$HOME/docker-projects/gitea/monitoring/reports/health_scores.csv"
    mkdir -p "$(dirname "$score_file")"
    
    if [ ! -f "$score_file" ]; then
        echo "timestamp,total_score,availability,performance,stability,efficiency" > "$score_file"
    fi
    
    echo "$(date +%s),$total_score,$availability_score,$performance_score,$stability_score,$efficiency_score" >> "$score_file"
}

calculate_health_score

🎛️ 实时监控仪表盘

为了提供直观的系统状态观察界面,我们需要一个实时更新的监控仪表盘。这个仪表盘就像汽车的仪表板一样,能够在一个界面上显示所有关键信息。

#!/bin/bash
# 实时监控仪表盘 - dashboard.sh
# 提供交互式的系统状态显示界面

# 终端控制和颜色定义
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'

# 清屏并显示头部信息
show_header() {
    clear
    echo -e "${BLUE}╔══════════════════════════════════════════════════════════════╗${NC}"
    echo -e "${BLUE}║                    🎯 Gitea实时监控仪表盘                      ║${NC}"
    echo -e "${BLUE}║                    $(date '+%Y-%m-%d %H:%M:%S')                    ║${NC}"
    echo -e "${BLUE}╚══════════════════════════════════════════════════════════════╝${NC}"
    echo
}

# 显示服务状态概览
show_service_overview() {
    echo -e "${CYAN}📊 服务状态概览${NC}"
    echo "────────────────────────────────────────"
    
    # Docker服务状态
    if docker info >/dev/null 2>&1; then
        echo -e "🐳 Docker服务:     ${GREEN}运行中${NC}"
    else
        echo -e "🐳 Docker服务:     ${RED}停止${NC}"
    fi
    
    # Gitea容器状态
    if docker ps | grep -q "gitea-app"then
        local uptime=$(docker inspect gitea-app --format='{{.State.StartedAt}}' | cut -d'T' -f1,2 | tr 'T' ' ')
        local restart_count=$(docker inspect gitea-app --format='{{.RestartCount}}')
        echo -e "📦 Gitea容器:      ${GREEN}运行中${NC}"
        echo -e "   └─ 启动时间:     $uptime"
        echo -e "   └─ 重启次数:     $restart_count"
    else
        echo -e "📦 Gitea容器:      ${RED}停止${NC}"
    fi
    
    # Web服务状态
    if curl -sf http://localhost:3000 >/dev/null 2>&1; then
        local response_time=$(curl -o /dev/null -s -w '%{time_total}' http://localhost:3000 2>/dev/null)
        local response_ms=$(echo "$response_time * 1000" | bc 2>/dev/null | cut -d. -f1)
        echo -e "🌐 Web服务:        ${GREEN}可达${NC} (${response_ms}ms)"
    else
        echo -e "🌐 Web服务:        ${RED}不可达${NC}"
    fi
    
    # SSH服务状态
    if nc -z localhost 2222 2>/dev/null; then
        echo -e "🔐 SSH服务:        ${GREEN}可达${NC} (端口2222)"
    else
        echo -e "🔐 SSH服务:        ${RED}不可达${NC}"
    fi
    
    echo
}

# 显示资源使用情况
show_resource_usage() {
    echo -e "${CYAN}💻 资源使用监控${NC}"
    echo "────────────────────────────────────────"
    
    local stats=$(docker stats gitea-app --no-stream --format "{{.CPUPerc}},{{.MemUsage}},{{.MemPerc}},{{.NetIO}},{{.BlockIO}}" 2>/dev/null)
    
    if [ -n "$stats" ]; then
        IFS=',' read -r cpu_usage mem_usage mem_percent net_io block_io <<< "$stats"
        
        # CPU使用率显示
        local cpu_num=$(echo "$cpu_usage" | sed 's/%//')
        if (( $(echo "$cpu_num < 20" | bc -l 2>/dev/null || echo 0) )); then
            echo -e "🔧 CPU使用率:      ${GREEN}$cpu_usage${NC}"
        elif (( $(echo "$cpu_num < 50" | bc -l 2>/dev/null || echo 0) )); then
            echo -e "🔧 CPU使用率:      ${YELLOW}$cpu_usage${NC}"
        else
            echo -e "🔧 CPU使用率:      ${RED}$cpu_usage${NC}"
        fi
        
        # 内存使用显示
        local mem_num=$(echo "$mem_percent" | sed 's/%//')
        if (( $(echo "$mem_num < 50" | bc -l 2>/dev/null || echo 0) )); then
            echo -e "🧠 内存使用:       ${GREEN}$mem_usage ($mem_percent)${NC}"
        elif (( $(echo "$mem_num < 80" | bc -l 2>/dev/null || echo 0) )); then
            echo -e "🧠 内存使用:       ${YELLOW}$mem_usage ($mem_percent)${NC}"
        else
            echo -e "🧠 内存使用:       ${RED}$mem_usage ($mem_percent)${NC}"
        fi
        
        # 网络I/O显示
        echo -e "🌐 网络I/O:        $net_io"
        
        # 磁盘I/O显示
        echo -e "💾 磁盘I/O:        $block_io"
    else
        echo -e "${RED}❌ 无法获取资源统计信息${NC}"
    fi
    
    # 磁盘空间状态
    local disk_info=$(df -h ~/docker-projects/gitea/gitea-data | tail -1)
    local disk_usage=$(echo "$disk_info" | awk '{print $5}' | sed 's/%//')
    local disk_avail=$(echo "$disk_info" | awk '{print $4}')
    
    if [ "$disk_usage" -lt 70 ]; then
        echo -e "📁 磁盘使用:       ${GREEN}${disk_usage}%${NC} (可用: $disk_avail)"
    elif [ "$disk_usage" -lt 85 ]; then
        echo -e "📁 磁盘使用:       ${YELLOW}${disk_usage}%${NC} (可用: $disk_avail)"
    else
        echo -e "📁 磁盘使用:       ${RED}${disk_usage}%${NC} (可用: $disk_avail)"
    fi
    
    echo
}

# 显示最近活动
show_recent_activity() {
    echo -e "${CYAN}📈 最近活动监控${NC}"
    echo "────────────────────────────────────────"
    
    # 获取最近5分钟的活动统计
    local recent_logs=$(docker-compose logs gitea --since 5m 2>/dev/null)
    
    if [ -n "$recent_logs" ]; then
        local get_requests=$(echo "$recent_logs" | grep -c "completed GET" || echo 0)
        local post_requests=$(echo "$recent_logs" | grep -c "completed POST" || echo 0)
        local errors=$(echo "$recent_logs" | grep -ci "error|fatal" || echo 0)
        
        echo -e "📊 5分钟活动统计:"
        echo -e "   └─ GET请求:      $get_requests 次"
        echo -e "   └─ POST请求:     $post_requests 次"
        echo -e "   └─ 错误记录:     $errors 条"
        
        # 显示最近的几条重要日志
        echo -e "📝 最近日志 (仅显示重要信息):"
        echo "$recent_logs" | grep -E "(error|fatal|warn|started|stopped)" | tail -3 | \
        while read -r line; do
            if echo "$line" | grep -qi "error|fatal"then
                echo -e "   ${RED}🚨 $line${NC}"
            elif echo "$line" | grep -qi "warn"then
                echo -e "   ${YELLOW}⚠️  $line${NC}"
            else
                echo -e "   ℹ️  $line"
            fi
        done
    else
        echo -e "ℹ️  最近5分钟内无明显活动"
    fi
    
    echo
}

# 显示操作菜单
show_menu() {
    echo -e "${CYAN}⚡ 快捷操作菜单${NC}"
    echo "────────────────────────────────────────"
    echo -e "${WHITE}[h]${NC} 运行健康检查     ${WHITE}[l]${NC} 查看完整日志"
    echo -e "${WHITE}[r]${NC} 重启Gitea服务    ${WHITE}[s]${NC} 系统状态详情"
    echo -e "${WHITE}[m]${NC} 生成监控报告     ${WHITE}[c]${NC} 清理系统资源"
    echo -e "${WHITE}[q]${NC} 退出仪表盘       ${WHITE}[?]${NC} 显示帮助"
    echo
    echo -e "${PURPLE}提示: 仪表盘每10秒自动刷新,按任意键立即刷新${NC}"
}

# 处理用户输入
handle_user_input() {
    local key
    if read -t 10 -n 1 -s key; then
        case $key in
            'h'|'H')
                echo "正在运行健康检查..."
                ./health-check.sh
                echo
                echo "按任意键返回仪表盘..."
                read -n 1 -s
                ;;
            'l'|'L')
                echo "显示实时日志 (按Ctrl+C返回仪表盘)..."
                docker-compose logs -f gitea
                ;;
            'r'|'R')
                echo "正在重启Gitea服务..."
                docker-compose restart gitea
                echo "重启完成,等待服务稳定..."
                sleep 5
                ;;
            's'|'S')
                echo "显示详细系统状态..."
                ./intelligent-monitor.sh status
                echo
                echo "按任意键返回仪表盘..."
                read -n 1 -s
                ;;
            'm'|'M')
                echo "正在生成监控报告..."
                ./intelligent-monitor.sh report
                echo "报告生成完成"
                sleep 2
                ;;
            'c'|'C')
                echo "正在清理系统资源..."
                docker system prune -f
                echo "清理完成"
                sleep 2
                ;;
            'q'|'Q')
                echo "退出监控仪表盘"
                exit 0
                ;;
            '?')
                echo
                echo -e "${CYAN}仪表盘帮助信息${NC}"
                echo "=============================="
                echo "这个仪表盘提供Gitea系统的实时监控信息"
                echo "自动刷新间隔: 10秒"
                echo "支持交互操作: 按对应字母键执行操作"
                echo "数据来源: Docker容器统计、应用日志、系统资源"
                echo
                echo "按任意键返回仪表盘..."
                read -n 1 -s
                ;;
        esac
    fi
}

# 主循环
main() {
    echo -e "${GREEN}启动Gitea监控仪表盘...${NC}"
    sleep 1
    
    while truedo
        show_header
        show_service_overview
        show_resource_usage
        show_recent_activity
        show_menu
        handle_user_input
    done
}

# 捕获退出信号
trap 'echo -e "\n${GREEN}感谢使用Gitea监控仪表盘!${NC}"; exit 0' INT TERM

main

🔄 自动化维护系统

定期维护任务配置

建立自动化的维护体系是确保系统长期稳定运行的关键。我们需要设计一套能够自动执行的维护任务,就像为汽车设定定期保养计划一样。

#!/bin/bash
# 自动化维护系统 - maintenance-system.sh
# 执行定期维护任务,确保系统长期稳定运行

MAINTENANCE_LOG="/Users/$(whoami)/docker-projects/gitea/monitoring/reports/maintenance.log"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# 创建维护日志目录
mkdir -p "$(dirname "$MAINTENANCE_LOG")"

# 记录维护日志的函数
log_maintenance() {
    local level=$1
    local message=$2
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] [$level$message" | tee -a "$MAINTENANCE_LOG"
}

# 每日维护任务
daily_maintenance() {
    log_maintenance "INFO" "开始执行每日维护任务"
    
    # 1. 系统健康检查
    log_maintenance "INFO" "执行系统健康检查"
    if "$SCRIPT_DIR/health-check.sh" | grep -q "❌"then
        log_maintenance "WARNING" "健康检查发现问题,需要人工关注"
    else
        log_maintenance "INFO" "系统健康检查通过"
    fi
    
    # 2. 日志轮转和清理
    log_maintenance "INFO" "执行日志清理"
    find "$(dirname "$MAINTENANCE_LOG")" -name "*.log" -mtime +30 -delete
    find "$(dirname "$MAINTENANCE_LOG")" -name "*.txt" -mtime +7 -delete
    
    # 3. Docker资源清理
    log_maintenance "INFO" "清理Docker资源"
    docker system prune -f >> "$MAINTENANCE_LOG" 2>&1
    
    # 4. 生成每日报告
    log_maintenance "INFO" "生成每日监控报告"
    "$SCRIPT_DIR/intelligent-monitor.sh" report
    
    # 5. 检查磁盘空间
    local disk_usage=$(df -h ~/docker-projects/gitea/gitea-data | tail -1 | awk '{print $5}' | sed 's/%//')
    if [ "$disk_usage" -gt 80 ]; then
        log_maintenance "WARNING" "磁盘使用率过高: ${disk_usage}%"
    else
        log_maintenance "INFO" "磁盘空间充足: ${disk_usage}%"
    fi
    
    log_maintenance "INFO" "每日维护任务完成"
}

# 每周维护任务
weekly_maintenance() {
    log_maintenance "INFO" "开始执行每周维护任务"
    
    # 1. 系统更新检查
    log_maintenance "INFO" "检查系统更新"
    if command -v brew >/dev/null; then
        brew outdated | tee -a "$MAINTENANCE_LOG"
    fi
    
    # 2. Docker镜像更新检查
    log_maintenance "INFO" "检查Docker镜像更新"
    docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.CreatedAt}}" | grep gitea | tee -a "$MAINTENANCE_LOG"
    
    # 3. 性能趋势分析
    log_maintenance "INFO" "执行性能趋势分析"
    if [ -f "$(dirname "$MAINTENANCE_LOG")/health_scores.csv" ]; then
        local avg_score=$(tail -7 "$(dirname "$MAINTENANCE_LOG")/health_scores.csv" | awk -F',' '{sum+=$2; count++} END {if(count>0) printf "%.1f", sum/count}')
        log_maintenance "INFO" "过去一周平均健康评分: $avg_score"
    fi
    
    # 4. 配置备份验证
    log_maintenance "INFO" "验证配置备份"
    if [ -f ~/docker-projects/gitea/docker-compose.yml ]; then
        cp ~/docker-projects/gitea/docker-compose.yml "$(dirname "$MAINTENANCE_LOG")/docker-compose-backup-$(date +%Y%m%d).yml"
        log_maintenance "INFO" "配置文件备份完成"
    fi
    
    # 5. 安全检查
    log_maintenance "INFO" "执行安全检查"
    docker scan gitea/gitea:latest >> "$MAINTENANCE_LOG" 2>&1 || log_maintenance "INFO" "Docker安全扫描完成(可能需要登录)"
    
    log_maintenance "INFO" "每周维护任务完成"
}

# 紧急维护任务
emergency_maintenance() {
    log_maintenance "CRITICAL" "执行紧急维护程序"
    
    # 1. 立即备份关键数据
    log_maintenance "CRITICAL" "执行紧急数据备份"
    local emergency_backup_dir="/tmp/gitea-emergency-backup-$(date +%Y%m%d_%H%M%S)"
    mkdir -p "$emergency_backup_dir"
    
    cp -r ~/docker-projects/gitea/gitea-data "$emergency_backup_dir/"
    cp ~/docker-projects/gitea/docker-compose.yml "$emergency_backup_dir/"
    
    log_maintenance "CRITICAL" "紧急备份完成: $emergency_backup_dir"
    
    # 2. 收集诊断信息
    log_maintenance "CRITICAL" "收集系统诊断信息"
    {
        echo "=== Docker系统信息 ==="
        docker info
        echo
        echo "=== 容器状态 ==="
        docker ps -a
        echo
        echo "=== 最近日志 ==="
        docker-compose logs gitea --tail 100
        echo
        echo "=== 系统资源 ==="
        df -h
        free -h 2>/dev/null || echo "内存信息不可用"
    } > "$emergency_backup_dir/diagnostic-info.txt"
    
    # 3. 尝试服务恢复
    log_maintenance "CRITICAL" "尝试服务恢复"
    docker-compose restart gitea
    sleep 30
    
    if curl -sf http://localhost:3000 >/dev/null 2>&1; then
        log_maintenance "INFO" "服务恢复成功"
    else
        log_maintenance "CRITICAL" "服务恢复失败,需要人工干预"
    fi
    
    log_maintenance "CRITICAL" "紧急维护程序完成"
}

# 设置定时任务
setup_cron_jobs() {
    log_maintenance "INFO" "设置定时维护任务"
    
    local cron_file="/tmp/gitea_maintenance_cron"
    
    cat > "$cron_file" << EOF
# Gitea自动化维护任务
# 每日凌晨2点执行日常维护
0 2 * * * cd $SCRIPT_DIR && ./maintenance-system.sh daily >> $MAINTENANCE_LOG 2>&1

# 每周日凌晨3点执行周维护
0 3 * * 0 cd $SCRIPT_DIR && ./maintenance-system.sh weekly >> $MAINTENANCE_LOG 2>&1

# 每10分钟执行健康检查
*/10 * * * * cd $SCRIPT_DIR && ./health-check.sh | grep -q "❌" && echo "健康检查发现问题: $(date)" >> $MAINTENANCE_LOG

# 每小时生成状态报告
0 * * * * cd $SCRIPT_DIR && ./intelligent-monitor.sh status >> $(dirname "$MAINTENANCE_LOG")/hourly-status.log 2>&1
EOF
    
    # 安装cron任务
    if crontab -l 2>/dev/null | grep -q "Gitea自动化维护"then
        log_maintenance "INFO" "更新现有维护任务"
        crontab -l 2>/dev/null | grep -v "Gitea.*维护|gitea.*maintenance" | crontab -
    fi
    
    (crontab -l 2>/dev/null; cat "$cron_file") | crontab -
    rm "$cron_file"
    
    log_maintenance "INFO" "定时维护任务设置完成"
}

# 主函数
main() {
    case "${1:-help}" in
        "daily")
            daily_maintenance
            ;;
        "weekly")
            weekly_maintenance
            ;;
        "emergency")
            emergency_maintenance
            ;;
        "setup-cron")
            setup_cron_jobs
            ;;
        "status")
            echo "维护系统状态:"
            echo "日志文件: $MAINTENANCE_LOG"
            echo "最近维护记录:"
            tail -10 "$MAINTENANCE_LOG" 2>/dev/null || echo "暂无维护记录"
            ;;
        *)
            echo "Gitea自动化维护系统"
            echo "用法: $0 [daily|weekly|emergency|setup-cron|status]"
            echo "  daily      - 执行每日维护任务"
            echo "  weekly     - 执行每周维护任务"  
            echo "  emergency  - 执行紧急维护程序"
            echo "  setup-cron - 设置定时任务"
            echo "  status     - 查看维护状态"
            ;;
    esac
}

main "$@"

🎓如何使用

现在监控系统已经组织的差不多了,那我们该如何使用呢。

让我们从最简单直接的监控开始。

# 首先确认你在正确的位置
cd /Users/leocoder/docker-projects/gitea/monitoring/scripts

# 运行基础健康检查 - 这是你每天应该查看的
./health-check.sh

image-20250607000426944

image-20250607000426944

这个命令会给你一个彩色的状态报告。当你看到绿色的勾号时,说明那个方面运行正常。黄色的警告符号表示需要关注但不紧急的问题。红色的错误标志则表示需要立即处理的问题。

image-20250607000450104

image-20250607000450104

# 运行智能状态分析 - 这会分析你的Gitea实际运行模式
./intelligent-monitor.sh status

image-20250607000522276

image-20250607000522276

这个命令会分析你的系统在过去一小时内的活动模式。它会告诉你收到了多少HTTP请求,平均响应时间是多少,是否检测到了规律性的监控活动等等。

# 运行健康评估 - 这会给你的系统打分
./health-assessment.sh

image-20250607000544412

image-20250607000544412

这个评分系统会从四个关键维度评估你的系统:服务可达性、响应性能、错误率和资源使用效率。每个维度都有具体的分数,最终给出一个总分。

理解这些信息的关键在于识别模式。如果你看到每隔几秒就有一个GET请求,这通常是健康检查的标志,是正常现象。如果响应时间都在几毫秒内,说明你的系统性能很好。如果发现大量POST请求,可能表明有用户在积极使用系统推送代码。

对于更深入的分析,我们可以生成详细的综合报告。这就像是医生为病人准备详细的体检报告,包含所有测试结果和专业分析。

# 生成综合分析报告
./intelligent-monitor.sh report

# 查看生成的报告文件
ls -la ../reports/

# 查看最新的报告内容
cat ../reports/comprehensive_analysis_*.txt | tail -50

image-20250607000617899

image-20250607000617899

这些报告会保存在reports目录中,你可以随时查看历史记录,比较不同时间的系统状态。这种历史数据的价值就像是医疗档案一样,能够帮助你识别长期趋势和周期性模式。

# 启动实时监控仪表盘
./dashboard.sh

image-20250607000706165

image-20250607000706165

这个仪表盘会每隔几秒自动刷新,显示当前的服务状态、资源使用情况和最近的活动。你可以通过按键进行交互操作,比如按"h"运行健康检查,按"l"查看实时日志等。

使用这个仪表盘时,要注意观察数值的变化趋势而不是绝对数值。如果CPU使用率突然上升,可能表明有大量用户在使用系统。如果内存使用量持续增长,可能需要关注是否存在内存泄漏。

当然,还可以通过以天,周单位来进行检查我们的系统。

每天早上工作开始时,运行一次每日检查脚本。这就像是医生每天查房一样,能够快速了解系统的整体状态。

image-20250607000739452

# 每天运行这个命令
./daily-check.sh

每周运行一次综合报告生成,用于了解系统的长期趋势。这就像是定期体检,能够发现仅靠日常观察难以察觉的缓慢变化。

image-20250607000936445

image-20250607000936445

# 每周运行这个命令
./intelligent-monitor.sh report

当系统出现异常或性能问题时,使用实时监控来深入观察。这就像是医生面对急诊病人时会使用更精密的监护设备一样。

image-20250607001056479

image-20250607001056479

# 问题排查时运行这个命令
./intelligent-monitor.sh monitor

📚 参考资源与进阶阅读

🔗 官方文档

这次分享就到这里,下次见。

本文使用 markdown.com.cn 排版