当前位置: 首页 > news >正文

基于Debian12的SVN和Trac自动安装部署脚本

SVN和Trac自动安装部署脚本使用说明

目录

  • 环境要求
  • 功能概述
  • 安装流程图
  • 配置信息
  • 插件说明
  • 使用方法
  • 故障排除
  • 最佳实践建议

环境要求

系统要求

  • Debian 12 (Bookworm) 操作系统
  • 至少1GB内存 (推荐2GB以上)
  • 至少10GB可用磁盘空间
  • root权限

网络要求

  • 互联网连接 (用于下载软件包和插件)
  • 可选:固定IP地址或域名 (用于外部访问)

软件依赖

脚本会自动安装以下软件:

  • Apache 2.4
  • PostgreSQL 最新稳定版
  • Python 3.x
  • Subversion
  • Redis (用于缓存)
  • Git (用于插件安装)

功能概述

该脚本提供以下功能:

  1. 环境准备

    • 系统更新
    • 依赖包安装
    • 环境冲突检测和清理
  2. SVN服务器安装

    • Subversion安装和配置
    • Apache与SVN集成
    • 基于Web的SVN访问
    • 用户认证和授权管理
  3. Trac项目管理系统安装

    • Trac核心安装
    • PostgreSQL/SQLite数据库配置
    • 与SVN集成
    • Web界面配置
  4. 增强插件安装

    • 用户管理插件
    • LDAP集成认证
    • 工作流管理
    • 票据模板和统计
    • 维基编辑器
    • 代码评论系统
    • 主题引擎
  5. 安全配置

    • SSL证书生成
    • 基本认证
    • 权限管理
  6. 故障修复

    • SVN权限修复
    • Apache配置修复
    • 插件问题诊断

安装流程图

开始安装
环境检查
系统更新
清理冲突环境
安装PostgreSQL
安装Redis
安装Apache
生成SSL证书
安装SVN
安装Python和Trac
安装Trac插件
配置Trac
配置Apache虚拟主机
修复SVN权限
安装完成
SVN修复模式
安装必要包
修复SVN权限
配置Apache
修复完成

配置信息

SVN配置

  • 仓库位置: /var/svn/repos
  • Web访问: http://svn.example.com/ (可自定义域名)
  • 认证方式: HTTP基本认证
  • 用户文件: /etc/apache2/dav_svn.passwd
  • 授权文件: /etc/apache2/dav_svn.authz
  • 日志位置: /var/log/apache2/svn_error.log

Trac配置

  • 项目位置: /var/trac/project
  • Web访问: http://trac.example.com/ (可自定义域名)
  • 数据库: 优先使用PostgreSQL,失败时回退到SQLite
  • 认证方式: HTTP基本认证
  • 用户文件: /var/trac/project/htpasswd/trac.htpasswd
  • 配置文件: /var/trac/project/conf/trac.ini
  • 日志位置: /var/log/apache2/trac_error.log

PostgreSQL配置

  • 数据库名: tracdb
  • 用户名: tracadmin
  • 密码: 自动生成 (安装完成后显示)
  • 优化设置: 根据系统内存自动配置

Apache配置

  • 虚拟主机: SVN和Trac各一个
  • 模块: dav, dav_svn, wsgi, ssl
  • 配置文件:
    • /etc/apache2/sites-available/svn.conf
    • /etc/apache2/sites-available/trac.conf

插件说明

插件名称功能描述配置位置
AccountManager用户管理、注册、密码重置管理 → 账户
TracLDAPLDAP目录服务集成认证trac.ini [ldap]
TracWorkflowAdmin工作流自定义管理管理 → 工作流
TracXMLRPCAPI访问接口无需配置
TracTicketTemplate票据模板管理新建票据页面
TracTicketStats票据统计和图表报表 → 统计
TracTags标签管理系统全站可用
TracWysiwyg所见即所得维基编辑器编辑维基页面时
TracAnnouncer高级通知系统trac.ini [announcer]
TracThemeEngine主题定制trac.ini [theme]
TracCodeComments代码审查和评论浏览源码时

使用方法

基本安装

  1. 下载脚本到服务器

    本页面最下方的代码复制粘贴到自己的文件中。
    
  2. 添加执行权限

    chmod +x install_svn_trac.sh
    
  3. 以root用户运行脚本

    sudo ./install_svn_trac.sh
    
  4. 按照提示输入SVN和Trac域名

    请输入SVN域名 (默认: svn.example.com): svn.your-domain.com
    请输入Trac域名 (默认: trac.example.com): trac.your-domain.com
    
  5. 如需配置LDAP认证,在提示时选择"y"并输入LDAP服务器信息

  6. 安装完成后,记录显示的账户信息

SVN修复模式

如果SVN访问出现问题,可以使用修复模式:

sudo ./install_svn_trac.sh fix-svn

访问服务

  1. 修改本地hosts文件或配置DNS,将域名指向服务器IP

  2. 访问SVN仓库:http://svn.your-domain.com/

  3. 访问Trac项目:http://trac.your-domain.com/

  4. 使用安装时创建的管理员账户登录

故障排除

常见问题

  1. Apache无法启动

    • 检查错误日志: cat /var/log/apache2/error.log
    • 检查配置: apache2ctl configtest
    • 可能原因: 端口冲突、模块缺失、配置错误
  2. SVN访问被拒绝

    • 检查权限: ls -la /var/svn
    • 检查认证文件: cat /etc/apache2/dav_svn.passwd
    • 运行修复命令: ./install_svn_trac.sh fix-svn
  3. Trac插件不工作

    • 检查插件安装: ls -la /opt/trac/plugins
    • 检查trac.ini配置: cat /var/trac/project/conf/trac.ini
    • 检查错误日志: cat /var/log/apache2/trac_error.log
  4. 数据库连接失败

    • 检查PostgreSQL状态: systemctl status postgresql
    • 测试连接: su - postgres -c "psql -c '\l'"
    • 检查密码: 查看安装日志中的PostgreSQL信息

日志文件位置

  • Apache主日志: /var/log/apache2/error.log
  • SVN日志: /var/log/apache2/svn_error.log
  • Trac日志: /var/log/apache2/trac_error.log
  • 安装日志: 脚本运行目录下的svn_trac_install_*.log

最佳实践建议

  1. 安全建议

    • 在生产环境中,建议使用HTTPS而非HTTP
    • 定期更改管理员密码
    • 限制对服务器的SSH访问
    • 配置防火墙只开放必要端口
  2. 性能优化

    • 对于大型项目,增加服务器内存
    • 考虑使用专用的PostgreSQL服务器
    • 启用Redis缓存以提高Trac性能
    • 定期备份SVN仓库和Trac数据库
  3. 维护建议

    • 定期更新系统和软件包
    • 监控磁盘空间使用情况
    • 设置日志轮转避免日志文件过大
    • 创建定期备份计划
  4. 扩展建议

    • 考虑集成CI/CD系统 (如Jenkins)
    • 添加邮件通知功能
    • 配置LDAP认证实现单点登录
    • 自定义Trac工作流以适应团队流程

附录:环境变量参考

变量名描述默认值
PGDB_PASSWORDPostgreSQL密码自动生成
SVN_ADMIN_PASSWORDSVN管理员密码自动生成
TRAC_ADMIN_PASSWORDTrac管理员密码自动生成
SVN_DOMAINSVN域名svn.example.com
TRAC_DOMAINTrac域名trac.example.com

其他说明

如有疑问,欢迎联系公众号“大刘讲IT”或QQ709840110

代码

#!/bin/bash

# 确保工作目录存在
ensure_working_directory() {
    # 尝试获取当前工作目录
    local current_dir
    current_dir=$(pwd 2>/dev/null)
    
    # 如果获取失败,切换到一个安全的目录
    if [ $? -ne 0 ]; then
        echo "警告: 无法获取当前工作目录,切换到/tmp目录"
        cd /tmp || cd / || {
            echo "严重错误: 无法切换到任何有效目录"
            exit 1
        }
    fi
    
    # 再次检查当前目录是否可访问
    if ! pwd &>/dev/null; then
        echo "严重错误: 仍然无法访问工作目录,请检查文件系统或权限问题"
        exit 1
    fi
    
    # 设置安全的工作目录
    SAFE_WORKING_DIR=$(pwd)
    echo "使用工作目录: $SAFE_WORKING_DIR"
}

# 在脚本开始时调用
ensure_working_directory

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # 无颜色

# 日志文件 - 使用绝对路径
LOG_FILE="$SAFE_WORKING_DIR/svn_trac_install_$(date +%Y%m%d_%H%M%S).log"
touch "$LOG_FILE" || {
    echo "无法创建日志文件,将使用/tmp目录"
    LOG_FILE="/tmp/svn_trac_install_$(date +%Y%m%d_%H%M%S).log"
    touch "$LOG_FILE" || {
        echo "无法在/tmp创建日志文件,将禁用日志记录"
        LOG_FILE="/dev/null"
    }
}

# 记录日志的函数
log() {
    local message="$1"
    local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
    echo -e "${timestamp} - ${message}" | tee -a "$LOG_FILE"
}

# 错误处理函数
error_exit() {
    log "${RED}错误: $1${NC}"
    exit 1
}

# 检查命令是否存在
check_command() {
    command -v "$1" >/dev/null 2>&1 || { error_exit "需要 $1 命令,但未找到。请安装后再试。"; }
}

# 检查是否为root用户
check_root() {
    if [ "$(id -u)" != "0" ]; then
        error_exit "此脚本必须以root用户身份运行"
    fi
}

# 检查系统是否为Debian 12
check_debian() {
    if [ ! -f /etc/debian_version ]; then
        error_exit "此脚本仅适用于Debian系统"
    fi
    
    local version=$(cat /etc/debian_version)
    if [[ ! $version =~ ^12 ]]; then
        log "${YELLOW}警告: 此脚本针对Debian 12优化,当前版本为 $version${NC}"
    fi
}

# 更新系统
update_system() {
    log "更新系统包列表..."
    apt update -y || error_exit "无法更新系统包列表"
    
    log "升级系统包..."
    apt upgrade -y || error_exit "无法升级系统包"
    
    log "安装基本工具..."
    apt install -y curl wget gnupg2 lsb-release apt-transport-https ca-certificates software-properties-common || error_exit "无法安装基本工具"
}

# 检查并清理冲突环境
check_and_clean_conflicts() {
    log "检查可能的环境冲突..."
    
    # 停止可能运行的服务
    log "停止可能运行的服务..."
    systemctl stop postgresql apache2 redis-server 2>/dev/null || true
    
    # 杀死可能残留的进程
    log "杀死可能残留的进程..."
    pkill -f apache2 || true
    pkill -f postgres || true
    pkill -f redis || true
    
    # 检查PostgreSQL
    if dpkg -l | grep -q postgresql; then
        log "${YELLOW}检测到已安装的PostgreSQL,将卸载...${NC}"
        
        # 删除所有PostgreSQL数据库和用户
        if command -v psql &> /dev/null; then
            log "尝试删除PostgreSQL数据库和用户..."
            su - postgres -c "psql -c \"DROP DATABASE IF EXISTS tracdb;\"" 2>/dev/null || log "${YELLOW}无法删除tracdb数据库${NC}"
            su - postgres -c "psql -c \"DROP USER IF EXISTS tracadmin;\"" 2>/dev/null || log "${YELLOW}无法删除tracadmin用户${NC}"
            
            # 断开所有连接
            su - postgres -c "psql -c \"SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname='tracdb';\"" 2>/dev/null || true
        fi
        
        # 完全卸载PostgreSQL
        apt purge -y postgresql* || log "${YELLOW}无法完全卸载PostgreSQL${NC}"
        apt autoremove -y --purge
        
        # 彻底清理PostgreSQL文件和目录
        find / -name "*postgres*" -type d -exec rm -rf {} \; 2>/dev/null || true
        find / -name "*postgresql*" -type d -exec rm -rf {} \; 2>/dev/null || true
        rm -rf /var/lib/postgresql || log "${YELLOW}无法删除PostgreSQL数据目录${NC}"
        rm -rf /etc/postgresql || log "${YELLOW}无法删除PostgreSQL配置目录${NC}"
        rm -rf /var/log/postgresql || log "${YELLOW}无法删除PostgreSQL日志目录${NC}"
        rm -rf /var/run/postgresql || log "${YELLOW}无法删除PostgreSQL运行目录${NC}"
        
        # 清理可能残留的PostgreSQL用户
        if id -u postgres &>/dev/null; then
            log "${YELLOW}尝试删除postgres系统用户...${NC}"
            userdel -rf postgres 2>/dev/null || log "${YELLOW}无法删除postgres用户${NC}"
        fi
        
        # 清理可能残留的PostgreSQL组
        if getent group postgres &>/dev/null; then
            log "${YELLOW}尝试删除postgres系统组...${NC}"
            groupdel postgres 2>/dev/null || log "${YELLOW}无法删除postgres组${NC}"
        fi
    fi
    
    # 检查Apache
    if dpkg -l | grep -q apache2; then
        log "${YELLOW}检测到已安装的Apache2,将卸载...${NC}"
        
        # 完全卸载Apache及其所有模块
        apt purge -y apache2* libapache2* || log "${YELLOW}无法完全卸载Apache2${NC}"
        apt autoremove -y --purge
        
        # 彻底清理Apache文件和目录
        find / -name "*apache*" -type d -exec rm -rf {} \; 2>/dev/null || true
        rm -rf /etc/apache2 || log "${YELLOW}无法删除Apache2配置目录${NC}"
        rm -rf /var/www || log "${YELLOW}无法删除Apache2网站目录${NC}"
        rm -rf /var/lib/apache2 || log "${YELLOW}无法删除Apache2库目录${NC}"
        rm -rf /var/log/apache2 || log "${YELLOW}无法删除Apache2日志目录${NC}"
        rm -rf /var/cache/apache2 || log "${YELLOW}无法删除Apache2缓存目录${NC}"
        rm -rf /run/apache2 || log "${YELLOW}无法删除Apache2运行目录${NC}"
        
        # 清理可能残留的Apache用户
        if id -u www-data &>/dev/null; then
            log "${YELLOW}重置www-data用户...${NC}"
            # 不删除www-data用户,因为它可能被其他服务使用,但重置其主目录
            usermod -d /var/www www-data 2>/dev/null || true
        fi
    fi
    
    # 检查SVN
    if dpkg -l | grep -q subversion; then
        log "${YELLOW}检测到已安装的Subversion,将卸载...${NC}"
        apt purge -y subversion* || log "${YELLOW}无法卸载Subversion${NC}"
        apt autoremove -y --purge
        
        # 彻底清理SVN文件和目录
        find / -name "*svn*" -type d -exec rm -rf {} \; 2>/dev/null || true
        rm -rf /var/svn || log "${YELLOW}无法完全删除SVN仓库${NC}"
        rm -rf /etc/subversion || log "${YELLOW}无法删除Subversion配置目录${NC}"
        rm -rf /usr/local/svn || log "${YELLOW}无法删除Subversion本地安装${NC}"
    fi
    
    # 检查Trac
    if pip3 list 2>/dev/null | grep -q trac; then
        log "${YELLOW}检测到已安装的Trac,将卸载...${NC}"
        pip3 uninstall -y trac || log "${YELLOW}无法卸载Trac${NC}"
    fi
    
    # 清理Trac环境
    find / -name "*trac*" -type d -exec rm -rf {} \; 2>/dev/null || true
    rm -rf /var/trac || log "${YELLOW}无法完全删除Trac文件${NC}"
    rm -rf /opt/trac || log "${YELLOW}无法删除Trac虚拟环境${NC}"
    rm -rf /usr/local/trac || log "${YELLOW}无法删除Trac本地安装${NC}"
    
    # 检查Redis
    if dpkg -l | grep -q redis; then
        log "${YELLOW}检测到已安装的Redis,将卸载...${NC}"
        apt purge -y redis* || log "${YELLOW}无法卸载Redis${NC}"
        apt autoremove -y --purge
        
        # 彻底清理Redis文件和目录
        find / -name "*redis*" -type d -exec rm -rf {} \; 2>/dev/null || true
        rm -rf /var/lib/redis || log "${YELLOW}无法删除Redis数据目录${NC}"
        rm -rf /etc/redis || log "${YELLOW}无法删除Redis配置目录${NC}"
        rm -rf /var/log/redis || log "${YELLOW}无法删除Redis日志目录${NC}"
        rm -rf /var/run/redis || log "${YELLOW}无法删除Redis运行目录${NC}"
    fi
    
    # 清理Python虚拟环境和包
    rm -rf ~/.cache/pip || true
    rm -rf /root/.cache/pip || true
    
    # 清理系统临时文件
    rm -rf /tmp/* || true
    
    # 清理可能残留的配置文件
    rm -f /etc/apt/sources.list.d/pgdg.list || true
    
    # 更新包列表
    apt update
    
    log "${GREEN}环境检查完成,已彻底清理可能的冲突${NC}"
    
    # 验证清理结果
    log "验证清理结果..."
    if dpkg -l | grep -q postgresql; then
        log "${RED}警告: PostgreSQL仍然存在,可能需要手动清理${NC}"
    fi
    if dpkg -l | grep -q apache2; then
        log "${RED}警告: Apache2仍然存在,可能需要手动清理${NC}"
    fi
    if dpkg -l | grep -q subversion; then
        log "${RED}警告: Subversion仍然存在,可能需要手动清理${NC}"
    fi
    if dpkg -l | grep -q redis; then
        log "${RED}警告: Redis仍然存在,可能需要手动清理${NC}"
    fi
}

# 安装PostgreSQL
install_postgresql() {
    log "安装PostgreSQL最新稳定版..."
    
    # 添加PostgreSQL官方仓库
    sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
    wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
    apt update
    
    # 安装PostgreSQL最新稳定版
    apt install -y postgresql postgresql-contrib || error_exit "无法安装PostgreSQL"
    
    # 确保PostgreSQL服务启动
    systemctl enable postgresql
    systemctl start postgresql
    
    # 生成随机密码(避免特殊字符)
    PGDB_PASSWORD=$(openssl rand -hex 12)
    
    # 创建数据库用户和数据库
    log "配置PostgreSQL用户和数据库..."
    su - postgres -c "psql -c \"DROP DATABASE IF EXISTS tracdb;\"" || log "${YELLOW}无法删除已存在的tracdb数据库${NC}"
    su - postgres -c "psql -c \"DROP USER IF EXISTS tracadmin;\"" || log "${YELLOW}无法删除已存在的tracadmin用户${NC}"
    su - postgres -c "psql -c \"CREATE USER tracadmin WITH PASSWORD '$PGDB_PASSWORD';\""
    su - postgres -c "psql -c \"CREATE DATABASE tracdb OWNER tracadmin;\""
    
    # 确保tracadmin用户有足够的权限
    su - postgres -c "psql -c \"GRANT ALL PRIVILEGES ON DATABASE tracdb TO tracadmin;\""
    
    # 优化PostgreSQL配置
    log "优化PostgreSQL性能配置..."
    
    # 获取系统内存信息(以KB为单位)
    local mem_total=$(grep MemTotal /proc/meminfo | awk '{print $2}')
    # 转换为MB
    local mem_total_mb=$((mem_total / 1024))
    
    # 根据系统内存计算合适的配置值
    local shared_buffers=$((mem_total_mb / 4))
    local effective_cache_size=$((mem_total_mb * 3 / 4))
    local work_mem=$((mem_total_mb / 16))
    local maintenance_work_mem=$((mem_total_mb / 8))
    
    # 确保最小值
    if [ $shared_buffers -lt 128 ]; then shared_buffers=128; fi
    if [ $work_mem -lt 4 ]; then work_mem=4; fi
    if [ $maintenance_work_mem -lt 16 ]; then maintenance_work_mem=16; fi
    
    # 备份原始配置
    cp /etc/postgresql/*/main/postgresql.conf /etc/postgresql/*/main/postgresql.conf.bak
    
    # 应用优化配置
    cat > /tmp/pg_config.sql << EOF
ALTER SYSTEM SET shared_buffers = '${shared_buffers}MB';
ALTER SYSTEM SET effective_cache_size = '${effective_cache_size}MB';
ALTER SYSTEM SET work_mem = '${work_mem}MB';
ALTER SYSTEM SET maintenance_work_mem = '${maintenance_work_mem}MB';
ALTER SYSTEM SET random_page_cost = 1.1;
ALTER SYSTEM SET effective_io_concurrency = 200;
ALTER SYSTEM SET max_worker_processes = 8;
ALTER SYSTEM SET max_parallel_workers_per_gather = 4;
ALTER SYSTEM SET max_parallel_workers = 8;
ALTER SYSTEM SET wal_buffers = '16MB';
ALTER SYSTEM SET checkpoint_completion_target = 0.9;
ALTER SYSTEM SET default_statistics_target = 100;
EOF
    
    su - postgres -c "psql -f /tmp/pg_config.sql"
    rm /tmp/pg_config.sql
    
    # 修改pg_hba.conf以允许密码认证
    PG_HBA_CONF=$(find /etc/postgresql -name pg_hba.conf | head -n 1)
    if [ -n "$PG_HBA_CONF" ]; then
        # 备份原始配置
        cp "$PG_HBA_CONF" "${PG_HBA_CONF}.bak"
        
        # 修改配置允许本地连接使用密码
        sed -i 's/local.*all.*all.*peer/local   all             all                                     md5/' "$PG_HBA_CONF"
        sed -i 's/host.*all.*all.*127.0.0.1\/32.*ident/host    all             all             127.0.0.1\/32            md5/' "$PG_HBA_CONF"
        sed -i 's/host.*all.*all.*::1\/128.*ident/host    all             all             ::1\/128                 md5/' "$PG_HBA_CONF"
        
        log "${GREEN}已修改PostgreSQL认证配置${NC}"
    else
        log "${YELLOW}找不到pg_hba.conf文件${NC}"
    fi
    
    # 重启PostgreSQL以应用更改
    systemctl restart postgresql
    
    # 测试数据库连接
    log "测试PostgreSQL连接..."
    if su - postgres -c "psql -c \"\\connect tracdb\""; then
        log "${GREEN}PostgreSQL连接测试成功${NC}"
    else
        log "${RED}PostgreSQL连接测试失败${NC}"
    fi
    
    log "${GREEN}PostgreSQL安装和优化完成${NC}"
    
    # 保存数据库信息
    PGDB_INFO="PostgreSQL用户名: tracadmin\nPostgreSQL密码: $PGDB_PASSWORD\nPostgreSQL数据库: tracdb"
}

# 安装Redis
install_redis() {
    log "安装Redis服务器..."
    apt install -y redis-server || error_exit "无法安装Redis"
    
    # 优化Redis配置
    log "优化Redis配置..."
    
    # 备份原始配置
    cp /etc/redis/redis.conf /etc/redis/redis.conf.bak
    
    # 应用优化配置
    sed -i 's/^# maxmemory .*/maxmemory 256mb/' /etc/redis/redis.conf
    sed -i 's/^# maxmemory-policy .*/maxmemory-policy allkeys-lru/' /etc/redis/redis.conf
    
    # 启用持久化
    sed -i 's/^appendonly no/appendonly yes/' /etc/redis/redis.conf
    
    # 重启Redis以应用更改
    systemctl restart redis-server
    systemctl enable redis-server
    
    log "${GREEN}Redis安装和优化完成${NC}"
}

# 安装Apache和依赖
install_apache() {
    log "安装Apache和依赖..."
    
    # 确保完全卸载旧的Apache安装
    apt purge -y apache2* libapache2* || log "${YELLOW}无法完全卸载旧的Apache安装${NC}"
    rm -rf /etc/apache2 || log "${YELLOW}无法删除Apache配置目录${NC}"
    
    # 安装Apache和必要的模块
    apt install -y apache2 apache2-bin apache2-utils || error_exit "无法安装Apache"
    
    # 安装SSL相关模块,特别是mod_socache_shmcb
    apt install -y apache2-ssl-dev || log "${YELLOW}无法安装Apache SSL开发包${NC}"
    
    # 确保安装了所有必要的Apache模块
    log "安装Apache模块..."
    apt install -y libapache2-mod-wsgi-py3 || error_exit "无法安装mod_wsgi模块"
    
    # 安装SVN模块
    log "安装SVN的Apache模块..."
    apt install -y libapache2-mod-svn || log "${YELLOW}无法安装libapache2-mod-svn,将在安装SVN时再次尝试${NC}"
    
    # 如果mod_python已安装,卸载它
    if dpkg -l | grep -q libapache2-mod-python; then
        log "${YELLOW}检测到mod_python已安装,正在卸载...${NC}"
        apt remove -y libapache2-mod-python
        # 确保mod_python模块被禁用
        if [ -f "/etc/apache2/mods-enabled/python.load" ]; then
            rm -f "/etc/apache2/mods-enabled/python.load"
        fi
        if [ -f "/etc/apache2/mods-enabled/python.conf" ]; then
            rm -f "/etc/apache2/mods-enabled/python.conf"
        fi
    fi
    
    # 确保mods-enabled目录存在
    mkdir -p /etc/apache2/mods-enabled
    
    # 启用必要的模块
    log "启用Apache模块..."
    
    # 首先启用socache_shmcb模块(SSL需要)
    if [ -f "/usr/sbin/a2enmod" ]; then
        /usr/sbin/a2enmod socache_shmcb || log "${YELLOW}无法使用a2enmod启用socache_shmcb模块${NC}"
    else
        if [ -f "/etc/apache2/mods-available/socache_shmcb.load" ]; then
            ln -sf "/etc/apache2/mods-available/socache_shmcb.load" "/etc/apache2/mods-enabled/socache_shmcb.load"
            log "${GREEN}已手动启用socache_shmcb模块${NC}"
        else
            log "${RED}找不到socache_shmcb模块,SSL可能无法正常工作${NC}"
        fi
    fi
    
    # 定义要启用的模块列表 - 移除dav_svn,将在安装SVN后启用
    MODULES=("ssl" "wsgi" "rewrite" "proxy" "proxy_http" "headers" "dav")
    
    # 循环启用每个模块
    for module in "${MODULES[@]}"; do
        log "启用模块: $module"
        if [ -f "/usr/sbin/a2enmod" ]; then
            /usr/sbin/a2enmod $module || log "${YELLOW}无法使用a2enmod启用$module模块${NC}"
        else
            if [ -f "/etc/apache2/mods-available/$module.load" ]; then
                ln -sf "/etc/apache2/mods-available/$module.load" "/etc/apache2/mods-enabled/$module.load"
                if [ -f "/etc/apache2/mods-available/$module.conf" ]; then
                    ln -sf "/etc/apache2/mods-available/$module.conf" "/etc/apache2/mods-enabled/$module.conf"
                fi
                log "${GREEN}已手动启用模块: $module${NC}"
            else
                log "${YELLOW}模块 $module 不存在,跳过...${NC}"
            fi
        fi
    done
    
    # 优化Apache配置
    log "优化Apache配置..."
    
    # 备份原始配置
    if [ -f /etc/apache2/apache2.conf ]; then
        cp /etc/apache2/apache2.conf /etc/apache2/apache2.conf.bak
    else
        log "${YELLOW}找不到Apache配置文件,跳过备份...${NC}"
    fi
    
    # 确保conf-available目录存在
    mkdir -p /etc/apache2/conf-available
    mkdir -p /etc/apache2/conf-enabled
    
    # 应用优化配置
    cat > /etc/apache2/conf-available/performance.conf << EOF
# Apache性能优化
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
<IfModule mpm_prefork_module>
    StartServers          5
    MinSpareServers       5
    MaxSpareServers      10
    MaxRequestWorkers    150
    MaxConnectionsPerChild   0
</IfModule>
EOF
    
    # 手动启用性能配置
    ln -sf /etc/apache2/conf-available/performance.conf /etc/apache2/conf-enabled/performance.conf
    log "${GREEN}已启用性能配置${NC}"
    
    # 禁用默认站点,避免冲突
    if [ -f /etc/apache2/sites-enabled/000-default.conf ]; then
        log "${YELLOW}禁用默认站点配置...${NC}"
        rm -f /etc/apache2/sites-enabled/000-default.conf
    fi
    
    # 检查Apache配置
    if [ -x "/usr/sbin/apache2ctl" ]; then
        if ! /usr/sbin/apache2ctl configtest; then
            log "${YELLOW}Apache配置存在语法错误,尝试修复...${NC}"
            
            # 检查SSL配置中是否缺少socache_shmcb模块
            if grep -q "SSLSessionCache.*shmcb" /etc/apache2/mods-enabled/ssl.conf; then
                log "${YELLOW}检测到SSL配置需要socache_shmcb模块,尝试修复...${NC}"
                
                # 修改SSL配置
                if [ -f "/etc/apache2/mods-enabled/ssl.conf" ]; then
                    # 备份原始配置
                    cp /etc/apache2/mods-enabled/ssl.conf /etc/apache2/mods-enabled/ssl.conf.bak
                    
                    # 注释掉可能导致问题的行
                    sed -i 's/^SSLSessionCache/#SSLSessionCache/' /etc/apache2/mods-enabled/ssl.conf
                    
                    log "${GREEN}已修复SSL配置${NC}"
                fi
            fi
        fi
    fi
    
    # 启用Apache服务
    systemctl enable apache2
    
    # 尝试启动Apache
    if ! systemctl start apache2; then
        log "${YELLOW}Apache启动失败,尝试查看错误日志...${NC}"
        if [ -f /var/log/apache2/error.log ]; then
            tail -n 20 /var/log/apache2/error.log | tee -a "$LOG_FILE"
        fi
        
        # 尝试修复常见问题
        log "${YELLOW}尝试修复Apache启动问题...${NC}"
        
        # 检查端口冲突
        if netstat -tuln | grep -q ':80\s'; then
            log "${RED}检测到端口80被占用,尝试停止占用进程...${NC}"
            fuser -k 80/tcp || log "${YELLOW}无法停止占用端口80的进程${NC}"
        fi
        
        # 再次尝试启动
        systemctl start apache2 || log "${RED}Apache仍然无法启动${NC}"
    else
        log "${GREEN}Apache启动成功${NC}"
    fi
    
    # 验证Apache是否正在运行
    if systemctl is-active --quiet apache2; then
        log "${GREEN}Apache安装和优化完成${NC}"
        return 0
    else
        log "${RED}Apache未能正常运行,但将继续安装过程${NC}"
        return 1
    fi
}

# 生成SSL证书
generate_ssl_certs() {
    local domain=$1
    local cert_dir="/etc/ssl/private"
    
    log "为 $domain 生成自签名SSL证书..."
    
    # 确保目录存在
    mkdir -p $cert_dir
    
    # 生成私钥和证书
    openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
        -keyout $cert_dir/$domain.key \
        -out $cert_dir/$domain.crt \
        -subj "/C=CN/ST=State/L=City/O=Organization/OU=IT/CN=$domain" \
        || error_exit "无法生成SSL证书"
    
    # 设置适当的权限
    chmod 600 $cert_dir/$domain.key
    chmod 644 $cert_dir/$domain.crt
    
    log "${GREEN}SSL证书生成完成${NC}"
}

# 安装SVN
install_svn() {
    log "安装Subversion..."
    apt install -y subversion || error_exit "无法安装Subversion"
    
    # 检查Apache是否已安装
    if ! command -v apache2 &> /dev/null; then
        log "${YELLOW}Apache可能未正确安装,尝试重新安装...${NC}"
        apt update
        apt install -y apache2 apache2-utils
    fi
    
    # 安装SVN的Apache模块
    log "安装SVN的Apache模块..."
    apt install -y libapache2-mod-svn || {
        log "${RED}无法安装libapache2-mod-svn,尝试替代方法...${NC}"
        # 尝试安装旧版本模块名称
        apt install -y libapache2-svn || log "${RED}无法安装SVN的Apache模块${NC}"
    }
    
    # 确保SVN模块已启用
    if [ -f "/usr/sbin/a2enmod" ]; then
        log "启用SVN相关模块..."
        /usr/sbin/a2enmod dav_svn || log "${YELLOW}无法启用dav_svn模块${NC}"
        /usr/sbin/a2enmod authz_svn || log "${YELLOW}无法启用authz_svn模块${NC}"
    else
        log "${YELLOW}找不到a2enmod命令,尝试手动启用SVN模块...${NC}"
        # 手动启用SVN模块
        if [ -f "/etc/apache2/mods-available/dav_svn.load" ]; then
            ln -sf "/etc/apache2/mods-available/dav_svn.load" "/etc/apache2/mods-enabled/dav_svn.load"
            if [ -f "/etc/apache2/mods-available/dav_svn.conf" ]; then
                ln -sf "/etc/apache2/mods-available/dav_svn.conf" "/etc/apache2/mods-enabled/dav_svn.conf"
            fi
            log "${GREEN}已手动启用dav_svn模块${NC}"
        else
            log "${RED}找不到dav_svn模块,SVN可能无法通过Web访问${NC}"
            
            # 尝试查找模块文件
            find /usr -name "*dav_svn*" -type f | while read -r file; do
                log "找到可能的SVN模块文件: $file"
            done
        fi
        
        if [ -f "/etc/apache2/mods-available/authz_svn.load" ]; then
            ln -sf "/etc/apache2/mods-available/authz_svn.load" "/etc/apache2/mods-enabled/authz_svn.load"
            if [ -f "/etc/apache2/mods-available/authz_svn.conf" ]; then
                ln -sf "/etc/apache2/mods-available/authz_svn.conf" "/etc/apache2/mods-enabled/authz_svn.conf"
            fi
            log "${GREEN}已手动启用authz_svn模块${NC}"
        fi
    fi
    
    # 创建SVN仓库目录
    mkdir -p /var/svn
    
    # 创建一个示例仓库
    log "创建示例SVN仓库..."
    svnadmin create /var/svn/repos
    
    # 设置权限 - 确保www-data用户有完全访问权限
    chown -R www-data:www-data /var/svn
    chmod -R 755 /var/svn
    
    # 创建一个简单的README文件
    log "初始化示例仓库内容..."
    mkdir -p /tmp/svn-import
    echo "# 示例SVN仓库" > /tmp/svn-import/README.md
    echo "这是一个由安装脚本自动创建的示例仓库。" >> /tmp/svn-import/README.md
    echo "创建时间: $(date)" >> /tmp/svn-import/README.md
    
    # 导入示例内容
    svn import -m "初始导入" /tmp/svn-import file:///var/svn/repos/trunk
    rm -rf /tmp/svn-import
    
    log "配置SVN访问控制..."
    
    # 创建SVN用户文件
    SVN_ADMIN_PASSWORD=$(openssl rand -base64 8)
    
    # 使用htpasswd创建密码文件
    apt install -y apache2-utils || log "${YELLOW}无法安装apache2-utils,将使用touch创建空密码文件${NC}"
    
    # 确保目录存在
    mkdir -p /etc/apache2
    
    # 创建密码文件
    if command -v htpasswd &> /dev/null; then
        htpasswd -bc /etc/apache2/dav_svn.passwd admin $SVN_ADMIN_PASSWORD
    else
        log "${YELLOW}找不到htpasswd命令,使用替代方法创建密码文件${NC}"
        # 使用openssl创建密码哈希
        PASS_HASH=$(openssl passwd -apr1 $SVN_ADMIN_PASSWORD)
        echo "admin:$PASS_HASH" > /etc/apache2/dav_svn.passwd
    fi
    
    # 确保密码文件权限正确
    chmod 640 /etc/apache2/dav_svn.passwd
    chown root:www-data /etc/apache2/dav_svn.passwd
    
    # 创建SVN授权文件
    log "创建SVN授权文件..."
    cat > /etc/apache2/dav_svn.authz << EOF
[groups]
admins = admin

[/]
@admins = rw
* = r

[repos:/]
@admins = rw
* = r
EOF
    chmod 644 /etc/apache2/dav_svn.authz
    chown root:www-data /etc/apache2/dav_svn.authz
    
    # 检查Apache配置
    if command -v apache2ctl &> /dev/null; then
        apache2ctl configtest || log "${YELLOW}Apache配置测试失败,可能需要手动修复${NC}"
    else
        log "${YELLOW}找不到apache2ctl命令,跳过配置测试...${NC}"
    fi
    
    # 重启Apache以应用SVN模块
    systemctl restart apache2 || log "${YELLOW}无法重启Apache服务${NC}"
    
    log "${GREEN}Subversion安装完成${NC}"
    
    # 保存SVN信息
    SVN_INFO="SVN管理员用户名: admin\nSVN管理员密码: $SVN_ADMIN_PASSWORD\nSVN仓库路径: /var/svn/repos"
}

# 修复SVN权限问题
fix_svn_permissions() {
    log "修复SVN权限问题..."
    
    # 确保SVN仓库目录存在
    if [ ! -d "/var/svn" ]; then
        log "${RED}SVN仓库目录不存在,创建目录...${NC}"
        mkdir -p /var/svn
    fi
    
    # 确保示例仓库存在
    if [ ! -d "/var/svn/repos" ]; then
        log "${RED}示例SVN仓库不存在,创建仓库...${NC}"
        svnadmin create /var/svn/repos
    fi
    
    # 设置正确的权限
    log "设置SVN仓库权限..."
    chown -R www-data:www-data /var/svn
    chmod -R 755 /var/svn
    
    # 确保Apache可以访问仓库
    usermod -a -G www-data www-data
    
    # 检查SVN模块是否已启用
    if [ -f "/usr/sbin/a2enmod" ]; then
        log "确保SVN模块已启用..."
        /usr/sbin/a2enmod dav_svn
        /usr/sbin/a2enmod authz_svn
    fi
    
    # 检查密码文件是否存在
    if [ ! -f "/etc/apache2/dav_svn.passwd" ]; then
        log "${RED}SVN密码文件不存在,创建默认密码文件...${NC}"
        SVN_ADMIN_PASSWORD=$(openssl rand -base64 8)
        htpasswd -bc /etc/apache2/dav_svn.passwd admin $SVN_ADMIN_PASSWORD
        chmod 640 /etc/apache2/dav_svn.passwd
        chown root:www-data /etc/apache2/dav_svn.passwd
        log "创建了新的SVN管理员密码: $SVN_ADMIN_PASSWORD"
    fi
    
    # 检查授权文件是否存在
    if [ ! -f "/etc/apache2/dav_svn.authz" ]; then
        log "${RED}SVN授权文件不存在,创建默认授权文件...${NC}"
        cat > /etc/apache2/dav_svn.authz << EOF
[groups]
admins = admin

[/]
@admins = rw
* = r

[repos:/]
@admins = rw
* = r
EOF
        chmod 644 /etc/apache2/dav_svn.authz
        chown root:www-data /etc/apache2/dav_svn.authz
    fi
    
    # 重启Apache
    log "重启Apache服务..."
    systemctl restart apache2
    
    log "${GREEN}SVN权限修复完成${NC}"
}

# 安装Python和Trac依赖
install_python_deps() {
    log "安装Python和Trac依赖..."
    apt install -y python3 python3-pip python3-dev python3-setuptools python3-wheel git || error_exit "无法安装Python和Git"
    
    # 安装LDAP相关依赖
    log "安装LDAP相关依赖..."
    apt install -y libldap2-dev libsasl2-dev || log "${YELLOW}无法安装LDAP开发库,LDAP认证可能无法正常工作${NC}"
    
    # 安装Python虚拟环境
    apt install -y python3-venv || error_exit "无法安装Python虚拟环境"
    
    # 创建虚拟环境
    mkdir -p /opt/trac
    python3 -m venv /opt/trac/venv
    
    # 安装Trac和依赖
    /opt/trac/venv/bin/pip install --upgrade pip
    
    # 安装特定版本的Trac和依赖,避免兼容性问题
    /opt/trac/venv/bin/pip install trac==1.4.3 || log "${YELLOW}无法安装指定版本的Trac,尝试安装最新版本...${NC}"
    /opt/trac/venv/bin/pip install trac || error_exit "无法安装Trac"
    
    # 安装PostgreSQL适配器
    /opt/trac/venv/bin/pip install psycopg2-binary || log "${YELLOW}无法安装psycopg2-binary,Trac将无法使用PostgreSQL${NC}"
    
    # 安装Redis支持
    /opt/trac/venv/bin/pip install redis || log "${YELLOW}无法安装Redis Python客户端,Trac将不使用Redis缓存${NC}"
    
    # 创建插件目录
    mkdir -p /opt/trac/plugins
    cd /opt/trac/plugins || log "${RED}无法切换到插件目录${NC}"
    
    # 安装常用Trac插件
    log "安装常用Trac插件..."
    
    # 用户管理插件 - 从PyPI安装
    /opt/trac/venv/bin/pip install TracAccountManager || log "${YELLOW}无法安装TracAccountManager插件${NC}"
    
    # LDAP认证插件 - 从源码安装
    /opt/trac/venv/bin/pip install python-ldap || log "${YELLOW}无法安装python-ldap库${NC}"
    
    # 尝试从GitHub安装TracLDAP
    log "从GitHub安装TracLDAP插件..."
    if [ ! -d "/opt/trac/plugins/trac-ldap" ]; then
        git clone https://github.com/trac-hacks/trac-ldap.git || log "${YELLOW}无法克隆TracLDAP仓库${NC}"
        if [ -d "/opt/trac/plugins/trac-ldap" ]; then
            cd /opt/trac/plugins/trac-ldap || log "${RED}无法切换到TracLDAP目录${NC}"
            /opt/trac/venv/bin/pip install -e . || log "${YELLOW}无法安装TracLDAP插件${NC}"
            cd /opt/trac/plugins || log "${RED}无法返回插件目录${NC}"
        fi
    fi
    
    # 安装替代的工作流插件 - TracWorkflowAdmin
    log "安装工作流插件(替代方案)..."
    if [ ! -d "/opt/trac/plugins/trac-workflowadmin" ]; then
        git clone https://github.com/trac-hacks/trac-workflowadmin.git || log "${YELLOW}无法克隆TracWorkflowAdmin仓库${NC}"
        if [ -d "/opt/trac/plugins/trac-workflowadmin" ]; then
            cd /opt/trac/plugins/trac-workflowadmin || log "${RED}无法切换到TracWorkflowAdmin目录${NC}"
            /opt/trac/venv/bin/pip install -e . || log "${YELLOW}无法安装TracWorkflowAdmin插件${NC}"
            cd /opt/trac/plugins || log "${RED}无法返回插件目录${NC}"
        fi
    fi
    
    # XML-RPC插件(用于API访问)- 已成功安装,无需修改
    /opt/trac/venv/bin/pip install TracXMLRPC || log "${YELLOW}无法安装TracXMLRPC插件${NC}"
    
    # 高级票据管理 - 从GitHub安装
    log "安装票据模板插件(替代方案)..."
    if [ ! -d "/opt/trac/plugins/trac-tickettemplate" ]; then
        git clone https://github.com/trac-hacks/trac-tickettemplate.git || log "${YELLOW}无法克隆TracTicketTemplate仓库${NC}"
        if [ -d "/opt/trac/plugins/trac-tickettemplate" ]; then
            cd /opt/trac/plugins/trac-tickettemplate || log "${RED}无法切换到TracTicketTemplate目录${NC}"
            /opt/trac/venv/bin/pip install -e . || log "${YELLOW}无法安装TracTicketTemplate插件${NC}"
            cd /opt/trac/plugins || log "${RED}无法返回插件目录${NC}"
        fi
    fi
    
    # 图表插件 - 使用TracTicketStatistics作为替代
    log "安装票据统计插件(替代方案)..."
    if [ ! -d "/opt/trac/plugins/trac-ticketstats" ]; then
        git clone https://github.com/trac-hacks/trac-ticketstats.git || log "${YELLOW}无法克隆TracTicketStats仓库${NC}"
        if [ -d "/opt/trac/plugins/trac-ticketstats" ]; then
            cd /opt/trac/plugins/trac-ticketstats || log "${RED}无法切换到TracTicketStats目录${NC}"
            /opt/trac/venv/bin/pip install -e . || log "${YELLOW}无法安装TracTicketStats插件${NC}"
            cd /opt/trac/plugins || log "${RED}无法返回插件目录${NC}"
        fi
    fi
    
    # 标签插件 - 从GitHub安装
    log "安装标签插件..."
    if [ ! -d "/opt/trac/plugins/trac-tags" ]; then
        git clone https://github.com/trac-hacks/trac-tags-plugin.git trac-tags || log "${YELLOW}无法克隆TracTags仓库${NC}"
        if [ -d "/opt/trac/plugins/trac-tags" ]; then
            cd /opt/trac/plugins/trac-tags || log "${RED}无法切换到TracTags目录${NC}"
            /opt/trac/venv/bin/pip install -e . || log "${YELLOW}无法安装TracTags插件${NC}"
            cd /opt/trac/plugins || log "${RED}无法返回插件目录${NC}"
        fi
    fi
    
    # 维基增强插件 - 使用TracWysiwyg作为替代
    log "安装维基编辑器插件(替代方案)..."
    if [ ! -d "/opt/trac/plugins/trac-wysiwyg" ]; then
        git clone https://github.com/trac-hacks/trac-wysiwyg.git || log "${YELLOW}无法克隆TracWysiwyg仓库${NC}"
        if [ -d "/opt/trac/plugins/trac-wysiwyg" ]; then
            cd /opt/trac/plugins/trac-wysiwyg || log "${RED}无法切换到TracWysiwyg目录${NC}"
            /opt/trac/venv/bin/pip install -e . || log "${YELLOW}无法安装TracWysiwyg插件${NC}"
            cd /opt/trac/plugins || log "${RED}无法返回插件目录${NC}"
        fi
    fi
    
    # 通知插件 - 使用TracAnnouncer作为替代
    log "安装通知插件(替代方案)..."
    if [ ! -d "/opt/trac/plugins/trac-announcer" ]; then
        git clone https://github.com/trac-hacks/trac-announcer.git || log "${YELLOW}无法克隆TracAnnouncer仓库${NC}"
        if [ -d "/opt/trac/plugins/trac-announcer" ]; then
            cd /opt/trac/plugins/trac-announcer || log "${RED}无法切换到TracAnnouncer目录${NC}"
            /opt/trac/venv/bin/pip install -e . || log "${YELLOW}无法安装TracAnnouncer插件${NC}"
            cd /opt/trac/plugins || log "${RED}无法返回插件目录${NC}"
        fi
    fi
    
    # 安装其他有用的插件
    
    # 主题插件
    log "安装主题插件..."
    /opt/trac/venv/bin/pip install TracThemeEngine || log "${YELLOW}无法安装TracThemeEngine插件${NC}"
    
    # 代码审查插件
    log "安装代码审查插件..."
    if [ ! -d "/opt/trac/plugins/trac-code-comments" ]; then
        git clone https://github.com/trac-hacks/trac-code-comments.git || log "${YELLOW}无法克隆TracCodeComments仓库${NC}"
        if [ -d "/opt/trac/plugins/trac-code-comments" ]; then
            cd /opt/trac/plugins/trac-code-comments || log "${RED}无法切换到TracCodeComments目录${NC}"
            /opt/trac/venv/bin/pip install -e . || log "${YELLOW}无法安装TracCodeComments插件${NC}"
            cd /opt/trac/plugins || log "${RED}无法返回插件目录${NC}"
        fi
    fi
    
    # 返回原始目录
    cd "$SAFE_WORKING_DIR" || log "${YELLOW}无法返回原始工作目录${NC}"
    
    # 设置插件目录权限
    chown -R www-data:www-data /opt/trac/plugins
    
    log "${GREEN}Python和Trac依赖安装完成${NC}"
}

# 配置Trac插件
configure_trac_plugins() {
    local trac_project_path=$1
    log "配置Trac插件..."
    
    # 检查trac.ini文件是否存在
    if [ ! -f "$trac_project_path/conf/trac.ini" ]; then
        log "${RED}找不到trac.ini文件,无法配置插件${NC}"
        return 1
    fi
    
    # 备份原始配置
    cp "$trac_project_path/conf/trac.ini" "$trac_project_path/conf/trac.ini.bak"
    
    # 添加插件配置
    log "启用插件组件..."
    cat >> "$trac_project_path/conf/trac.ini" << EOF

[components]
# 用户管理插件
acct_mgr.admin.*                    = enabled
acct_mgr.api.*                      = enabled
acct_mgr.db.*                       = enabled
acct_mgr.htfile.*                   = enabled
acct_mgr.http.*                     = enabled
acct_mgr.notification.*             = enabled
acct_mgr.pwhash.*                   = enabled
acct_mgr.register.*                 = enabled
acct_mgr.web_ui.*                   = enabled
acct_mgr.guard.*                    = enabled

# 标签插件
tractags.*                          = enabled

# 工作流插件
workflowadmin.*                     = enabled

# XML-RPC插件
tracrpc.*                           = enabled

# 票据模板插件
tickettemplate.*                    = enabled

# 票据统计插件
ticketstats.*                       = enabled

# 维基编辑器插件
tracwysiwyg.*                       = enabled

# 通知插件
announcer.*                         = enabled

# 主题插件
themeengine.*                       = enabled

# 代码评论插件
codecomments.*                      = enabled

[account-manager]
password_store = HtPasswdStore
password_file = /var/trac/project/htpasswd/trac.htpasswd
account_changes_notify_addresses = 
authentication_url = 
force_passwd_change = true
hash_method = crypt
htpasswd_hash_type = crypt
htpasswd_file = /var/trac/project/htpasswd/trac.htpasswd
password_format = $apr1$(.+?)$(.+)
refresh_passwd = false
user_lock_max_time = 0
verify_email = true
login_attempt_max_count = 3
login_opt_list = True
persistent_sessions = True
cookie_refresh_interval = 1

[theme]
theme = default
disable_trac_css = false

[ticketstats]
stats_interval = 30
stats_default_interval = 30
EOF
    
    # 配置LDAP认证(如果需要)
    read -p "是否配置LDAP认证? (y/n, 默认: n): " CONFIGURE_LDAP
    CONFIGURE_LDAP=${CONFIGURE_LDAP:-n}
    
    if [ "$CONFIGURE_LDAP" = "y" ] || [ "$CONFIGURE_LDAP" = "Y" ]; then
        log "配置LDAP认证..."
        
        # 获取LDAP配置信息
        read -p "LDAP服务器地址 (例如: ldap://ldap.example.com): " LDAP_SERVER
        read -p "LDAP基础DN (例如: dc=example,dc=com): " LDAP_BASE_DN
        read -p "LDAP绑定DN (例如: cn=admin,dc=example,dc=com): " LDAP_BIND_DN
        read -p "LDAP绑定密码: " LDAP_BIND_PASSWORD
        read -p "LDAP用户过滤器 (例如: (objectClass=person)): " LDAP_USER_FILTER
        
        # 添加LDAP配置
        cat >> "$trac_project_path/conf/trac.ini" << EOF

[ldap]
enable = true
basedn = ${LDAP_BASE_DN}
host = ${LDAP_SERVER}
user_rdn = ${LDAP_BIND_DN}
user_filter = ${LDAP_USER_FILTER}
password = ${LDAP_BIND_PASSWORD}

[components]
ldapplugin.* = enabled
EOF
        
        log "${GREEN}LDAP认证配置完成${NC}"
    else
        log "跳过LDAP认证配置"
    fi
    
    # 配置通知
    cat >> "$trac_project_path/conf/trac.ini" << EOF

[notification]
smtp_enabled = false
smtp_server = localhost
smtp_port = 25
smtp_user = 
smtp_password = 
use_tls = false
smtp_from = trac@localhost
smtp_replyto = trac@localhost
smtp_always_cc = 
smtp_always_bcc = 

[announcer]
email_enabled = false
email_sender = SmtpEmailSender
smtp_server = localhost
smtp_port = 25
smtp_user = 
smtp_password = 
use_tls = false
smtp_from = trac-announcer@localhost
smtp_replyto = trac-announcer@localhost
EOF
    
    # 配置工作流
    cat >> "$trac_project_path/conf/trac.ini" << EOF

[ticket-workflow]
accept = new,assigned,accepted,reopened -> accepted
accept.operations = set_owner_to_self
accept.permissions = TICKET_MODIFY
leave = * -> *
leave.operations = leave_status
leave.default = 1
reassign = new,assigned,accepted,reopened -> assigned
reassign.operations = set_owner
reassign.permissions = TICKET_MODIFY
reopen = closed -> reopened
reopen.operations = del_resolution
reopen.permissions = TICKET_CREATE
resolve = new,assigned,accepted,reopened -> closed
resolve.operations = set_resolution
resolve.permissions = TICKET_MODIFY
EOF
    
    # 配置代码评论
    cat >> "$trac_project_path/conf/trac.ini" << EOF

[codecomments]
comments_path = /var/trac/project/code-comments
enable_email = false
EOF
    
    # 创建代码评论目录
    mkdir -p /var/trac/project/code-comments
    chown -R www-data:www-data /var/trac/project/code-comments
    
    log "${GREEN}Trac插件配置完成${NC}"
}

# 配置Trac
configure_trac() {
    log "配置Trac..."
    
    # 创建Trac项目目录
    mkdir -p /var/trac
    
    # 检查是否已存在Trac项目
    if [ -d "/var/trac/project" ]; then
        log "${YELLOW}检测到已存在的Trac项目,将删除并重新创建...${NC}"
        rm -rf /var/trac/project
    fi
    
    # 确保目录存在且权限正确
    mkdir -p /var/trac
    chown -R www-data:www-data /var/trac
    
    # 获取Trac版本信息
    TRAC_VERSION=$(/opt/trac/venv/bin/trac-admin --version | head -n 1)
    log "Trac版本: $TRAC_VERSION"
    
    # 测试PostgreSQL连接
    log "测试PostgreSQL连接..."
    if PGPASSWORD="${PGDB_PASSWORD}" psql -h localhost -U tracadmin -d tracdb -c "\l" > /dev/null 2>&1; then
        log "${GREEN}PostgreSQL连接测试成功${NC}"
        USE_POSTGRES=true
    else
        log "${YELLOW}PostgreSQL连接测试失败,将使用SQLite作为备选${NC}"
        USE_POSTGRES=false
    fi
    
    # 创建一个示例Trac项目
    log "初始化Trac项目环境..."
    
    # 确保项目目录不存在
    rm -rf /var/trac/project
    
    # 尝试不同的数据库连接方式
    if [ "$USE_POSTGRES" = true ]; then
        log "尝试使用PostgreSQL初始化Trac..."
        
        # 尝试多种PostgreSQL连接字符串格式
        DB_CONN_STRINGS=(
            "postgres://tracadmin:${PGDB_PASSWORD}@localhost:5432/tracdb"
            "postgresql://tracadmin:${PGDB_PASSWORD}@localhost:5432/tracdb"
            "postgres://tracadmin:${PGDB_PASSWORD}@localhost/tracdb"
            "postgresql://tracadmin:${PGDB_PASSWORD}@localhost/tracdb"
        )
        
        INIT_SUCCESS=false
        for conn_string in "${DB_CONN_STRINGS[@]}"; do
            log "尝试连接字符串: $conn_string"
            if /opt/trac/venv/bin/trac-admin /var/trac/project initenv "示例项目" "$conn_string"; then
                log "${GREEN}使用连接字符串 '$conn_string' 成功初始化Trac项目${NC}"
                INIT_SUCCESS=true
                break
            fi
        done
        
        if [ "$INIT_SUCCESS" = false ]; then
            log "${YELLOW}所有PostgreSQL连接尝试均失败,将使用SQLite作为备选...${NC}"
            USE_POSTGRES=false
        fi
    fi
    
    # 如果PostgreSQL连接失败,使用SQLite
    if [ "$USE_POSTGRES" = false ]; then
        log "使用SQLite初始化Trac..."
        
        # 确保SQLite目录存在
        mkdir -p /var/trac/project/db
        
        # 尝试使用SQLite初始化
        if ! /opt/trac/venv/bin/trac-admin /var/trac/project initenv "示例项目" "sqlite:db/trac.db"; then
            log "${RED}SQLite初始化也失败,尝试手动创建基本环境...${NC}"
            
            # 手动创建Trac环境
            mkdir -p /var/trac/project/conf
            mkdir -p /var/trac/project/db
            mkdir -p /var/trac/project/log
            mkdir -p /var/trac/project/plugins
            mkdir -p /var/trac/project/htdocs
            
            # 创建空的SQLite数据库文件
            touch /var/trac/project/db/trac.db
            
            # 创建最小配置文件
            cat > /var/trac/project/conf/trac.ini << EOF
[header_logo]
alt = 示例项目
height = -1
link = 
src = site/your_project_logo.png
width = -1

[project]
descr = 示例Trac项目
footer = 访问 <a href="https://trac.edgewall.org/">Trac开源项目</a>
icon = common/trac.ico
name = 示例项目
url = 

[trac]
base_url = 
database = sqlite:db/trac.db
admin = admin
EOF
            
            # 尝试使用trac-admin初始化数据库
            if /opt/trac/venv/bin/trac-admin /var/trac/project upgrade; then
                log "${GREEN}成功升级Trac数据库${NC}"
            else
                log "${RED}无法升级Trac数据库,尝试创建基本表结构...${NC}"
                
                # 尝试使用sqlite3命令行工具创建基本表结构
                if command -v sqlite3 &> /dev/null; then
                    # 安装sqlite3(如果尚未安装)
                    apt install -y sqlite3
                    
                    # 创建基本表结构
                    sqlite3 /var/trac/project/db/trac.db << EOF
CREATE TABLE system (
    name TEXT PRIMARY KEY,
    value TEXT
);
INSERT INTO system VALUES ('database_version', '45');
CREATE TABLE permission (
    username TEXT,
    action TEXT,
    UNIQUE (username, action)
);
INSERT INTO permission VALUES ('admin', 'TRAC_ADMIN');
EOF
                    log "${GREEN}已手动创建基本SQLite表结构${NC}"
                else
                    log "${RED}找不到sqlite3命令,无法创建基本表结构${NC}"
                fi
            fi
            
            log "${YELLOW}已手动创建基本Trac环境${NC}"
        else
            log "${GREEN}已使用SQLite成功初始化Trac项目${NC}"
        fi
        
        PGDB_INFO="$PGDB_INFO\n注意: Trac使用SQLite数据库而非PostgreSQL"
    fi
    
    # 设置权限
    chown -R www-data:www-data /var/trac
    
    # 创建Trac管理员用户
    TRAC_ADMIN_PASSWORD=$(openssl rand -hex 8)
    log "配置Trac管理员..."
    
    # 获取trac-admin帮助信息
    /opt/trac/venv/bin/trac-admin /var/trac/project help > /tmp/trac-admin-help.txt 2>&1
    
    # 尝试不同的命令格式添加管理员
    if grep -q "permission add" /tmp/trac-admin-help.txt; then
        log "使用 'permission add' 命令添加管理员权限..."
        if /opt/trac/venv/bin/trac-admin /var/trac/project permission add admin TRAC_ADMIN; then
            log "${GREEN}成功添加管理员权限${NC}"
        else
            log "${YELLOW}无法使用permission add命令添加管理员权限,尝试直接修改数据库...${NC}"
            
            # 如果使用SQLite,尝试直接修改数据库
            if [ "$USE_POSTGRES" = false ] && command -v sqlite3 &> /dev/null; then
                if sqlite3 /var/trac/project/db/trac.db "INSERT OR REPLACE INTO permission VALUES ('admin', 'TRAC_ADMIN');"; then
                    log "${GREEN}已直接在SQLite数据库中添加管理员权限${NC}"
                else
                    log "${RED}无法在SQLite数据库中添加管理员权限${NC}"
                fi
            fi
        fi
    fi
    
    # 手动修改trac.ini文件确保管理员设置存在
    log "确保trac.ini中包含管理员设置..."
    if [ -f "/var/trac/project/conf/trac.ini" ]; then
        # 检查是否已有[trac]部分
        if grep -q "^\[trac\]" /var/trac/project/conf/trac.ini; then
            # 检查是否已有admin设置
            if ! grep -q "^admin = " /var/trac/project/conf/trac.ini; then
                # 在[trac]部分添加admin设置
                sed -i '/^\[trac\]/a admin = admin' /var/trac/project/conf/trac.ini
                log "${GREEN}已在trac.ini中添加管理员设置${NC}"
            fi
        else
            # 添加[trac]部分和admin设置
            echo -e "\n[trac]\nadmin = admin" >> /var/trac/project/conf/trac.ini
            log "${GREEN}已添加[trac]部分和管理员设置${NC}"
        fi
    fi
    
    # 创建htpasswd文件用于基本认证
    log "创建htpasswd文件用于基本认证..."
    mkdir -p /var/trac/project/htpasswd
    htpasswd -bc /var/trac/project/htpasswd/trac.htpasswd admin "$TRAC_ADMIN_PASSWORD"
    chown -R www-data:www-data /var/trac/project/htpasswd
    
    # 配置Trac插件
    configure_trac_plugins "/var/trac/project"
    
    # 创建WSGI脚本目录
    mkdir -p /var/trac/project/cgi-bin
    
    # 创建WSGI脚本
    cat > /var/trac/project/cgi-bin/trac.wsgi << EOF
import os
import sys

# 设置环境变量
os.environ['PYTHON_EGG_CACHE'] = '/var/trac/project/.egg-cache'

# 添加虚拟环境路径
python_version = '.'.join(map(str, sys.version_info[:2]))
sys.path.insert(0, '/opt/trac/venv/lib/python{}/site-packages'.format(python_version))

# 设置Trac环境路径
trac_env = '/var/trac/project'
os.environ['TRAC_ENV'] = trac_env

# 导入Trac WSGI应用
from trac.web.main import dispatch_request
application = dispatch_request

# 配置Redis缓存(如果可用)
try:
    import redis
    from trac.web.main import dispatch_request
    from trac.web.session import Session
    
    class RedisSession(Session):
        def __init__(self, env, req):
            super(RedisSession, self).__init__(env, req)
            self.redis = redis.Redis(host='localhost', port=6379, db=0)
            
        def _load(self):
            sid = self.sid
            if sid:
                data = self.redis.get('trac:session:' + sid)
                if data:
                    return eval(data)
            return {}
            
        def _save(self):
            if not self.sid:
                self.sid = self._generate_sid()
            self.redis.set('trac:session:' + self.sid, repr(self.data))
            self.redis.expire('trac:session:' + self.sid, 86400 * 30)  # 30天过期
    
    # 替换Session类
    trac.web.main.Session = RedisSession
except Exception as e:
    # 记录错误但不中断
    print("Redis缓存配置失败:", str(e))
EOF
    
    # 设置WSGI脚本权限
    chown -R www-data:www-data /var/trac/project/cgi-bin
    chmod 755 /var/trac/project/cgi-bin/trac.wsgi
    
    # 创建.egg-cache目录并设置权限
    mkdir -p /var/trac/project/.egg-cache
    chown www-data:www-data /var/trac/project/.egg-cache
    
    log "${GREEN}Trac配置完成${NC}"
    
    # 保存Trac信息
    TRAC_INFO="Trac管理员用户名: admin\nTrac管理员密码: $TRAC_ADMIN_PASSWORD"
}

# 配置Apache虚拟主机
configure_apache_vhosts() {
    local svn_domain=$1
    local trac_domain=$2
    
    log "配置Apache虚拟主机..."
    
    # 检查Apache是否已安装
    if ! command -v apache2 &> /dev/null; then
        log "${YELLOW}Apache可能未正确安装,尝试重新安装...${NC}"
        apt update
        apt install -y apache2 apache2-utils libapache2-mod-wsgi-py3
        
        # 安装SSL相关模块
        apt install -y apache2-ssl-dev
    fi
    
    # 确保必要的目录存在
    mkdir -p /etc/apache2/sites-available
    mkdir -p /etc/apache2/sites-enabled
    
    # 确保所有必要的模块都已启用
    log "确保所有必要的Apache模块都已启用..."
    
    # 首先启用socache_shmcb模块(SSL需要)
    if [ -f "/usr/sbin/a2enmod" ]; then
        /usr/sbin/a2enmod socache_shmcb
        /usr/sbin/a2enmod ssl
        /usr/sbin/a2enmod wsgi
        /usr/sbin/a2enmod rewrite
        /usr/sbin/a2enmod proxy
        /usr/sbin/a2enmod proxy_http
        /usr/sbin/a2enmod headers
        /usr/sbin/a2enmod dav
        /usr/sbin/a2enmod dav_svn
        /usr/sbin/a2enmod authz_svn
    else
        log "${YELLOW}找不到a2enmod命令,尝试手动启用模块...${NC}"
        # 手动启用模块
        for module in socache_shmcb ssl wsgi rewrite proxy proxy_http headers dav dav_svn authz_svn; do
            if [ -f "/etc/apache2/mods-available/$module.load" ]; then
                ln -sf "/etc/apache2/mods-available/$module.load" "/etc/apache2/mods-enabled/$module.load"
                if [ -f "/etc/apache2/mods-available/$module.conf" ]; then
                    ln -sf "/etc/apache2/mods-available/$module.conf" "/etc/apache2/mods-enabled/$module.conf"
                fi
                log "${GREEN}已手动启用模块: $module${NC}"
            else
                log "${YELLOW}模块 $module 不存在,跳过...${NC}"
            fi
        done
    fi
    
    # 修复SSL配置
    if [ -f "/etc/apache2/mods-enabled/ssl.conf" ]; then
        # 检查是否有SSLSessionCache配置
        if grep -q "SSLSessionCache.*shmcb" /etc/apache2/mods-enabled/ssl.conf; then
            # 备份原始配置
            cp /etc/apache2/mods-enabled/ssl.conf /etc/apache2/mods-enabled/ssl.conf.bak
            
            # 注释掉可能导致问题的行
            sed -i 's/^SSLSessionCache/#SSLSessionCache/' /etc/apache2/mods-enabled/ssl.conf
            
            log "${GREEN}已修复SSL配置${NC}"
        fi
    fi
    
    # SVN虚拟主机配置 - 修改为更详细的配置
    cat > /etc/apache2/sites-available/svn.conf << EOF
<VirtualHost *:80>
    ServerName ${svn_domain}
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html
    
    # 启用SVN
    <Location />
        DAV svn
        SVNParentPath /var/svn
        
        # 认证设置
        AuthType Basic
        AuthName "Subversion Repository"
        AuthUserFile /etc/apache2/dav_svn.passwd
        Require valid-user
        
        # 添加SVN特定设置
        SVNListParentPath On
        SVNAutoversioning On
        
        # 确保权限正确
        <IfModule mod_authz_svn.c>
            AuthzSVNAccessFile /etc/apache2/dav_svn.authz
        </IfModule>
    </Location>
    
    # 设置目录权限
    <Directory /var/svn>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>
    
    # 日志设置
    ErrorLog \${APACHE_LOG_DIR}/svn_error.log
    CustomLog \${APACHE_LOG_DIR}/svn_access.log combined
</VirtualHost>
EOF

    # 创建SVN授权文件(如果不存在)
    if [ ! -f /etc/apache2/dav_svn.authz ]; then
        log "创建SVN授权文件..."
        cat > /etc/apache2/dav_svn.authz << EOF
[groups]
admins = admin

[/]
@admins = rw
* = r
EOF
        chmod 644 /etc/apache2/dav_svn.authz
        chown root:www-data /etc/apache2/dav_svn.authz
    fi
    
    # Trac虚拟主机配置(使用HTTP而非HTTPS,避免SSL问题)
    cat > /etc/apache2/sites-available/trac.conf << EOF
<VirtualHost *:80>
    ServerName ${trac_domain}
    
    # 获取Python版本
    WSGIDaemonProcess trac user=www-data group=www-data python-home=/opt/trac/venv
    WSGIProcessGroup trac
    
    WSGIScriptAlias / /var/trac/project/cgi-bin/trac.wsgi
    
    <Directory /var/trac/project/cgi-bin>
        WSGIApplicationGroup %{GLOBAL}
        Require all granted
    </Directory>
    
    <Location "/">
        AuthType Basic
        AuthName "Trac"
        AuthUserFile /var/trac/project/htpasswd/trac.htpasswd
        Require valid-user
    </Location>
    
    ErrorLog \${APACHE_LOG_DIR}/trac_error.log
    CustomLog \${APACHE_LOG_DIR}/trac_access.log combined
</VirtualHost>
EOF
    
    # 手动启用站点
    ln -sf /etc/apache2/sites-available/svn.conf /etc/apache2/sites-enabled/
    ln -sf /etc/apache2/sites-available/trac.conf /etc/apache2/sites-enabled/
    
    # 禁用默认站点,避免冲突
    if [ -f /etc/apache2/sites-enabled/000-default.conf ]; then
        log "${YELLOW}禁用默认站点配置...${NC}"
        rm -f /etc/apache2/sites-enabled/000-default.conf
    fi
    
    # 检查Apache配置
    if [ -x "/usr/sbin/apache2ctl" ]; then
        if ! /usr/sbin/apache2ctl configtest; then
            log "${YELLOW}Apache配置存在语法错误,尝试修复...${NC}"
            
            # 显示详细错误
            /usr/sbin/apache2ctl -t -D DUMP_MODULES || log "${YELLOW}无法显示Apache模块${NC}"
        fi
    fi
    
    # 重启Apache
    log "重启Apache服务..."
    systemctl restart apache2 || {
        log "${YELLOW}Apache重启失败,尝试修复...${NC}"
        
        # 显示错误日志
        if [ -f /var/log/apache2/error.log ]; then
            log "Apache错误日志:"
            tail -n 20 /var/log/apache2/error.log
        fi
        
        # 尝试使用不同的方法重启Apache
        if [ -x "/usr/sbin/apache2ctl" ]; then
            /usr/sbin/apache2ctl stop
            sleep 2
            /usr/sbin/apache2ctl start
        else
            systemctl stop apache2
            sleep 2
            systemctl start apache2
        fi
    }
    
    # 检查Apache是否正在运行
    if systemctl is-active --quiet apache2; then
        log "${GREEN}Apache服务已成功启动${NC}"
    else
        log "${RED}Apache服务未能启动${NC}"
    fi
    
    log "${GREEN}Apache虚拟主机配置完成${NC}"
}

# 主函数
main() {
    # 记录开始时间
    START_TIME=$(date +%s)
    
    log "${BLUE}开始安装Trac和SVN...${NC}"
    
    # 检查是否为root用户
    check_root
    
    # 检查系统是否为Debian
    check_debian
    
    # 提示用户输入域名
    log "请输入SVN和Trac域名信息"
    read -p "请输入SVN域名 (默认: svn.example.com): " SVN_DOMAIN
    SVN_DOMAIN=${SVN_DOMAIN:-svn.example.com}
    
    read -p "请输入Trac域名 (默认: trac.example.com): " TRAC_DOMAIN
    TRAC_DOMAIN=${TRAC_DOMAIN:-trac.example.com}
    
    log "SVN域名: ${SVN_DOMAIN}"
    log "Trac域名: ${TRAC_DOMAIN}"
    
    # 更新系统
    update_system
    
    # 检查并清理冲突环境
    check_and_clean_conflicts
    
    # 安装PostgreSQL
    install_postgresql
    
    # 安装Redis
    install_redis
    
    # 安装Apache和依赖
    if ! install_apache; then
        log "${YELLOW}Apache安装可能存在问题,但将继续安装过程...${NC}"
    fi
    
    # 生成SSL证书
    generate_ssl_certs $SVN_DOMAIN
    generate_ssl_certs $TRAC_DOMAIN
    
    # 安装SVN
    install_svn
    
    # 安装Python和Trac依赖
    install_python_deps
    
    # 配置Trac
    configure_trac
    
    # 配置Apache虚拟主机
    configure_apache_vhosts $SVN_DOMAIN $TRAC_DOMAIN
    
    # 修复SVN权限问题
    fix_svn_permissions
    
    # 记录结束时间并计算总用时
    END_TIME=$(date +%s)
    TOTAL_TIME=$((END_TIME - START_TIME))
    HOURS=$((TOTAL_TIME / 3600))
    MINUTES=$(( (TOTAL_TIME % 3600) / 60 ))
    SECONDS=$((TOTAL_TIME % 60))
    
    # 显示安装信息
    log "${GREEN}安装完成!${NC}"
    log "总用时: ${HOURS}小时 ${MINUTES}分钟 ${SECONDS}秒"
    log "SVN仓库地址: http://${SVN_DOMAIN}/"
    log "Trac项目地址: http://${TRAC_DOMAIN}/"
    
    # 显示数据库信息(如果变量存在)
    if [ -n "$PGDB_INFO" ]; then
        log "PostgreSQL信息:"
        echo -e "$PGDB_INFO" | while IFS= read -r line; do log "$line"; done
    fi
    
    # 显示SVN信息(如果变量存在)
    if [ -n "$SVN_INFO" ]; then
        log "SVN信息:"
        echo -e "$SVN_INFO" | while IFS= read -r line; do log "$line"; done
    fi
    
    # 显示Trac信息(如果变量存在)
    if [ -n "$TRAC_INFO" ]; then
        log "Trac信息:"
        echo -e "$TRAC_INFO" | while IFS= read -r line; do log "$line"; done
    fi
    
    # 显示Trac插件信息
    log "已安装的Trac插件:"
    log "- AccountManager: 用户管理插件,提供用户注册、密码重置等功能"
    log "- TracLDAP: LDAP集成认证插件(从GitHub安装)"
    log "- TracWorkflowAdmin: 工作流管理插件(替代TracWorkflow)"
    log "- TracXMLRPC: XML-RPC接口插件,提供API访问"
    log "- TracTicketTemplate: 票据模板插件(从GitHub安装)"
    log "- TracTicketStats: 票据统计插件(替代TracTicketCharts)"
    log "- TracTags: 标签插件(从GitHub安装)"
    log "- TracWysiwyg: 所见即所得维基编辑器(替代TracWikiExtras)"
    log "- TracAnnouncer: 高级通知插件(替代TracNotification)"
    log "- TracThemeEngine: 主题引擎插件,支持自定义界面"
    log "- TracCodeComments: 代码评论插件,支持代码审查"
    
    log "插件使用指南:"
    log "1. 登录Trac后,访问 '管理' -> '插件' 页面可以查看和配置已安装的插件"
    log "2. 用户管理功能位于 '管理' -> '账户' 菜单下"
    log "3. 如需启用LDAP认证,请编辑 /var/trac/project/conf/trac.ini 文件,配置[ldap]部分"
    log "4. 所有插件都已安装在 /opt/trac/plugins 目录下,可以根据需要修改"
    
    log "注意: 您可能需要在hosts文件中添加以下条目:"
    log "127.0.0.1 ${SVN_DOMAIN}"
    log "127.0.0.1 ${TRAC_DOMAIN}"
    log "安装日志已保存到: ${LOG_FILE}"
    
    # 检查安装结果
    check_installation_result
    
    return 0
}

# 检查安装结果
check_installation_result() {
    log "检查安装结果..."
    
    # 检查Apache是否运行
    if systemctl is-active --quiet apache2; then
        log "${GREEN}Apache服务正在运行${NC}"
    else
        log "${RED}警告: Apache服务未运行${NC}"
    fi
    
    # 检查PostgreSQL是否运行
    if systemctl is-active --quiet postgresql; then
        log "${GREEN}PostgreSQL服务正在运行${NC}"
    else
        log "${RED}警告: PostgreSQL服务未运行${NC}"
    fi
    
    # 检查SVN仓库是否存在
    if [ -d "/var/svn/repos" ]; then
        log "${GREEN}SVN仓库已创建${NC}"
    else
        log "${RED}警告: SVN仓库未创建${NC}"
    fi
    
    # 检查Trac环境是否存在
    if [ -d "/var/trac/project" ]; then
        log "${GREEN}Trac环境已创建${NC}"
    else
        log "${RED}警告: Trac环境未创建${NC}"
    fi
    
    # 检查SVN模块是否已启用
    if [ -f "/etc/apache2/mods-enabled/dav_svn.load" ]; then
        log "${GREEN}SVN模块已启用${NC}"
    else
        log "${RED}警告: SVN模块未启用${NC}"
    fi
    
    # 检查SVN配置文件
    if [ -f "/etc/apache2/sites-enabled/svn.conf" ]; then
        log "${GREEN}SVN虚拟主机配置已启用${NC}"
    else
        log "${RED}警告: SVN虚拟主机配置未启用${NC}"
    fi
    
    # 检查Trac插件是否已安装
    log "检查Trac插件安装状态..."
    
    # 检查AccountManager插件
    if [ -d "/opt/trac/venv/lib/python3.*/site-packages/acct_mgr" ] || [ -f "/opt/trac/venv/lib/python3.*/site-packages/acct_mgr" ]; then
        log "${GREEN}AccountManager插件已安装${NC}"
    else
        log "${YELLOW}警告: AccountManager插件可能未正确安装${NC}"
    fi
    
    # 检查从GitHub安装的插件
    if [ -d "/opt/trac/plugins/trac-ldap" ]; then
        log "${GREEN}TracLDAP插件已安装${NC}"
    else
        log "${YELLOW}警告: TracLDAP插件可能未正确安装${NC}"
    fi
    
    if [ -d "/opt/trac/plugins/trac-workflowadmin" ]; then
        log "${GREEN}TracWorkflowAdmin插件已安装${NC}"
    else
        log "${YELLOW}警告: TracWorkflowAdmin插件可能未正确安装${NC}"
    fi
    
    if [ -d "/opt/trac/plugins/trac-tickettemplate" ]; then
        log "${GREEN}TracTicketTemplate插件已安装${NC}"
    else
        log "${YELLOW}警告: TracTicketTemplate插件可能未正确安装${NC}"
    fi
    
    if [ -d "/opt/trac/plugins/trac-ticketstats" ]; then
        log "${GREEN}TracTicketStats插件已安装${NC}"
    else
        log "${YELLOW}警告: TracTicketStats插件可能未正确安装${NC}"
    fi
    
    if [ -d "/opt/trac/plugins/trac-tags" ]; then
        log "${GREEN}TracTags插件已安装${NC}"
    else
        log "${YELLOW}警告: TracTags插件可能未正确安装${NC}"
    fi
    
    if [ -d "/opt/trac/plugins/trac-wysiwyg" ]; then
        log "${GREEN}TracWysiwyg插件已安装${NC}"
    else
        log "${YELLOW}警告: TracWysiwyg插件可能未正确安装${NC}"
    fi
    
    if [ -d "/opt/trac/plugins/trac-announcer" ]; then
        log "${GREEN}TracAnnouncer插件已安装${NC}"
    else
        log "${YELLOW}警告: TracAnnouncer插件可能未正确安装${NC}"
    fi
    
    if [ -d "/opt/trac/plugins/trac-code-comments" ]; then
        log "${GREEN}TracCodeComments插件已安装${NC}"
    else
        log "${YELLOW}警告: TracCodeComments插件可能未正确安装${NC}"
    fi
    
    # 提供故障排除建议
    log "如果遇到问题,请检查以下日志文件:"
    log "Apache错误日志: /var/log/apache2/error.log"
    log "Trac错误日志: /var/log/apache2/trac_error.log"
    log "SVN错误日志: /var/log/apache2/svn_error.log"
    
    log "您可以使用以下命令检查Apache状态:"
    log "systemctl status apache2"
    log "apache2ctl -t"
    
    log "您可以使用以下命令检查PostgreSQL状态:"
    log "systemctl status postgresql"
    log "su - postgres -c \"psql -c '\\l'\""
    
    log "如果SVN访问出现问题,可以运行以下命令修复:"
    log "bash $0 fix-svn"
    
    log "如果需要重新配置Trac插件,可以编辑以下文件:"
    log "/var/trac/project/conf/trac.ini"
    
    log "如果插件安装失败,可以尝试手动安装:"
    log "cd /opt/trac/plugins && git clone https://github.com/trac-hacks/插件名称.git"
    log "cd 插件目录 && /opt/trac/venv/bin/pip install -e ."
}

# 单独修复SVN问题的函数
fix_svn_only() {
    log "${BLUE}开始修复SVN问题...${NC}"
    
    # 检查是否为root用户
    check_root
    
    # 安装必要的包
    apt update
    apt install -y apache2 apache2-utils libapache2-mod-svn subversion
    
    # 修复SVN权限
    fix_svn_permissions
    
    # 重新配置Apache虚拟主机
    read -p "请输入SVN域名 (默认: svn.example.com): " SVN_DOMAIN
    SVN_DOMAIN=${SVN_DOMAIN:-svn.example.com}
    
    # SVN虚拟主机配置 - 修改为更详细的配置
    cat > /etc/apache2/sites-available/svn.conf << EOF
<VirtualHost *:80>
    ServerName ${SVN_DOMAIN}
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html
    
    # 启用SVN
    <Location />
        DAV svn
        SVNParentPath /var/svn
        
        # 认证设置
        AuthType Basic
        AuthName "Subversion Repository"
        AuthUserFile /etc/apache2/dav_svn.passwd
        Require valid-user
        
        # 添加SVN特定设置
        SVNListParentPath On
        SVNAutoversioning On
        
        # 确保权限正确
        <IfModule mod_authz_svn.c>
            AuthzSVNAccessFile /etc/apache2/dav_svn.authz
        </IfModule>
    </Location>
    
    # 设置目录权限
    <Directory /var/svn>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>
    
    # 日志设置
    ErrorLog \${APACHE_LOG_DIR}/svn_error.log
    CustomLog \${APACHE_LOG_DIR}/svn_access.log combined
</VirtualHost>
EOF
    
    # 启用站点
    ln -sf /etc/apache2/sites-available/svn.conf /etc/apache2/sites-enabled/
    
    # 重启Apache
    systemctl restart apache2
    
    log "${GREEN}SVN修复完成!${NC}"
    log "SVN仓库地址: http://${SVN_DOMAIN}/"
    
    # 显示SVN信息(如果变量存在)
    if [ -n "$SVN_ADMIN_PASSWORD" ]; then
        log "SVN管理员用户名: admin"
        log "SVN管理员密码: $SVN_ADMIN_PASSWORD"
    else
        log "SVN管理员用户名: admin"
        log "SVN管理员密码: 请查看 /etc/apache2/dav_svn.passwd 文件"
    fi
    
    log "注意: 您可能需要在hosts文件中添加以下条目:"
    log "127.0.0.1 ${SVN_DOMAIN}"
}

# 调用主函数开始安装或修复
# 确保在安全的工作目录中执行
cd "$SAFE_WORKING_DIR" || {
    log "${RED}无法切换到安全的工作目录,将使用当前目录${NC}"
}

# 根据参数决定执行什么操作
if [ "$1" = "fix-svn" ]; then
    fix_svn_only
else
    # 捕获所有错误并记录
    main "$@" || {
        EXIT_CODE=$?
        log "${RED}安装过程失败,退出代码: $EXIT_CODE${NC}"
        log "请检查上述日志以获取详细错误信息"
        exit $EXIT_CODE
    }
fi 

相关文章:

  • upload-labs-master通关攻略(17~19)
  • RSA算法:开启现代密码学的数学之钥
  • SpringMVC中有关请求参数的问题(映射路径,传递不同的参数)
  • 前端小食堂 | Day13 - Vue.js 进阶烹饪术
  • RISC-V特权模式与寄存器
  • 计网面试准备
  • Vue的生命周期
  • Ubuntu 下 nginx-1.24.0 源码分析 - ngx_conf_param
  • FreeRTOS(7)队列集
  • Redis 主从复制详解:实现高可用与数据备份
  • 【MySQL - 表的内外连接】
  • 【13】单片机编程核心技巧:乘法运算
  • 《Python全栈开发》第2课:HTML骨架搭建 - 从零编写个人简历页面
  • 数字IC后端设计实现教程 |Innovus ICC2 Routing Pin Access Setting设置方法
  • 第十五届蓝桥杯大学B组(握手问题、小球反弹、好数)
  • ChatGPT课件分享(37页PPT)
  • 【亲测有效】Mac系统升级或降级Node.js版本,Mac系统调整node.js版本
  • 【3D视觉学习笔记1】针孔相机模型与坐标系变换
  • 【Azure 架构师学习笔记】- Azure Databricks (17) --Delta Live Table和Delta Table
  • 面试之《webpack从输入到输出经历了什么》
  • 英国和美国就关税贸易协议条款达成一致
  • 85后清华博士黄佐财任湖北咸宁市咸安区委副书记、代区长
  • 两部门发布外汇领域行刑反向衔接案例,织密金融安全“防护网”
  • 圆桌丨中俄权威专家详解:两国携手维护战后国际秩序,捍卫国际公平正义
  • 2025江西跨境电子商务发展交流会召开,探索行业发展新趋势
  • 媒体起底“速成洋文凭”灰产链,专家:我们要给学历“祛魅”