Skip to content

Latest commit

 

History

History
242 lines (183 loc) · 5.83 KB

File metadata and controls

242 lines (183 loc) · 5.83 KB

权限管理重构完成 ✅

重构成果

代码精简

  • 从 900 行减少到 176 行(-80%)
  • 从 8 个公开方法减少到 2 个(-75%)
  • 删除了 20+ 个未使用的私有方法
  • 删除了硬编码的目录列表

核心 API

// 启动前调用(只设置 MySQL 配置文件权限)
directory_permission_manager.ensure_mysql_config_safe()?;

// 失败时调用(可选的修复逻辑)
directory_permission_manager.fix_mysql_permissions_on_failure()?;

目录创建

// 目录创建由 DockerManager 自动处理(从 docker-compose.yml 读取)
docker_manager.ensure_host_volumes_exist().await?;

设计原则

职责分离

组件 职责 实现方式
DockerManager 自动检测 docker-compose.yml 并创建挂载目录 ensure_host_volumes_exist()
DirectoryPermissionManager 设置 MySQL 配置文件权限(644) ensure_mysql_config_safe()
Docker init 容器 修改数据目录所有权(chown 999:999) mysql-permission-fix 容器

为什么这样设计?

  1. 目录创建自动化

    • DockerManager 解析 docker-compose.yml
    • 自动检测所有 bind mount 的宿主机路径
    • 自动创建不存在的目录
    • 不需要硬编码目录列表
  2. chown 需要 root 权限

    • Rust 代码以普通用户运行,无法 chown
    • Docker init 容器以 root 运行,可靠地执行 chown
  3. 配置文件不需要 chown

    • MySQL 只需读取配置文件
    • 保持当前用户所有权即可
    • 只需确保权限是 644(MySQL 安全要求)
  4. chmod 失败通常不影响

    • WSL2/网络文件系统可能不支持标准权限
    • Docker 有自己的权限映射机制
    • 只要所有权正确,容器就能运行

删除的功能

被注释掉的调用(全部删除)

// ❌ 这些调用在代码中全部被注释掉了
progressive_permission_management()
post_container_start_maintenance()
check_and_fix_mysql_config_permissions()
post_mysql_start_permission_check()
basic_permission_fix()

过度设计的功能(全部删除)

// ❌ 这些功能试图处理所有边缘情况,但实际不需要
is_safe_to_clean_mysql_dir()
is_likely_user_data()
is_mysql_init_file()
safe_cleanup_mysql_init_files()
is_safe_init_directory()
fix_existing_mysql_permissions()
set_wsl2_permission()  // 从未被调用
is_wsl2_windows_mount()  // 从未被使用

保留的核心逻辑

1. 自动创建目录(DockerManager)

// 从 docker-compose.yml 自动检测挂载目录
docker_manager.ensure_host_volumes_exist().await?;

// 解析示例:
// volumes:
//   - ./data/mysql:/var/lib/mysql
//   - ./logs/mysql:/var/log/mysql
//   - ./config/mysql.cnf:/etc/mysql/conf.d/mysql.cnf:ro
// 
// 自动创建:
// - data/mysql/
// - logs/mysql/
// - config/ (mysql.cnf 的父目录)

2. 设置 MySQL 配置文件权限

// 关键:MySQL 会拒绝 group-writable 或 world-writable 的配置文件
// 必须设置为 644
chmod 644 config/mysql.cnf

3. 失败时的修复逻辑

// 只在 MySQL 启动失败时调用
// 设置最宽松权限(777)尝试修复
chmod 777 data/mysql/
chmod 644 config/mysql.cnf  // 配置文件仍然保持 644

配合的 Docker Compose 配置

mysql-permission-fix:
  image: busybox:1.36-uclibc
  volumes:
    - ./data/mysql:/var/lib/mysql
    - ./logs/mysql:/var/log/mysql
    # 注意:不挂载配置文件
  command: |
    chown -R 999:999 /var/lib/mysql /var/log/mysql
    chmod -R 755 /var/lib/mysql /var/log/mysql
  restart: "no"

mysql:
  depends_on:
    mysql-permission-fix:
      condition: service_completed_successfully
  volumes:
    - ./config/mysql.cnf:/etc/mysql/conf.d/mysql.cnf:ro  # 只读挂载

测试验证

1. 正常启动

cargo run -- docker-service start
# 应该成功启动所有服务

2. 配置文件权限自动修复

# 设置错误权限
chmod 777 config/mysql.cnf

# 启动服务
cargo run -- docker-service start

# 验证权限已修复
ls -la config/mysql.cnf
# 应该显示:-rw-r--r-- (644)

3. MySQL 配置生效验证

# 检查字符集配置
docker exec mysql mysql -uroot -p -e "SHOW VARIABLES LIKE 'character_set%';"

# 应该看到 utf8mb4(说明配置文件生效)

文档更新

  1. docs/docker-volume-permissions.md - 详细的权限机制说明
  2. docs/mysql-config-permissions-quick-ref.md - 快速参考
  3. docs/permission-refactoring-summary.md - 重构对比
  4. docs/REFACTORING_COMPLETE.md - 本文档

维护建议

不要再添加复杂的权限逻辑

如果遇到权限问题:

  1. 首先检查 Docker init 容器

    docker-compose logs mysql-permission-fix
  2. 检查配置文件权限

    ls -la config/mysql.cnf  # 应该是 644
  3. 检查 MySQL 日志

    docker logs mysql 2>&1 | grep -i "ignored\|permission"

如果需要添加新功能

问自己三个问题

  1. 这个功能是否可以在 Docker init 容器中实现?
  2. 这个功能是否真的需要?(还是"以防万一")
  3. 是否有更简单的方式?

记住

  • 简单 > 复杂
  • 可靠 > 完美
  • 实用 > 理论

总结

这次重构的核心思想:

不要试图在 Rust 代码中解决所有权限问题

  • Rust:创建目录 + 设置配置文件权限(644)
  • Docker:处理数据目录所有权(chown 999:999)
  • 简单、可靠、易维护

结果

  • ✅ 代码减少 75%
  • ✅ 复杂度大幅降低
  • ✅ 更易理解和维护
  • ✅ 功能完全保留
  • ✅ 测试更容易

教训

  • ❌ 过度设计是技术债务
  • ❌ "以防万一"的代码通常不需要
  • ❌ 被注释掉的代码应该删除
  • ✅ 简单的设计更可靠
  • ✅ 职责分离很重要