#!/bin/bash set -e echo "=== ThinkPHP Docker权限初始化 ===" # 定义应用根目录,优先使用环境变量,否则使用默认值 APP_ROOT="${PHP_APP_ROOT:-/var/www/html}" echo "使用应用根目录: $APP_ROOT" # 创建统一的Web组并配置所有用户(最高效的权限管理) configure_web_users() { # 常见Web服务器用户列表 WEB_USERS=("www-data" "www" "apache" "nginx") # 获取环境变量中的用户ID TARGET_UID=${USER_ID:-33} TARGET_GID=${GROUP_ID:-33} echo "配置统一Web组权限,目标UID:GID = $TARGET_UID:$TARGET_GID" # 创建统一的Web组 WEB_GROUP="webaccess" if ! getent group "$WEB_GROUP" &>/dev/null; then echo "创建统一Web组: $WEB_GROUP" groupadd -g $TARGET_GID "$WEB_GROUP" || echo "创建 $WEB_GROUP 组失败" else echo "统一Web组 $WEB_GROUP 已存在" fi # 只将已存在的Web用户加入统一组(不创建新用户) for web_user in "${WEB_USERS[@]}"; do if id "$web_user" &>/dev/null; then echo "Web用户 $web_user 已存在,加入统一组" usermod -g $WEB_GROUP "$web_user" 2>/dev/null || echo "将 $web_user 加入 $WEB_GROUP 失败" else echo "Web用户 $web_user 不存在,跳过" fi done echo "统一Web组配置完成" } configure_web_users echo "当前用户: $(whoami)" echo "UID: $(id -u), GID: $(id -g)" # 修复所有目录权限(使用统一Web组,最高效的权限管理) if [ -d "$APP_ROOT" ]; then WEB_GROUP="webaccess" echo "修复应用目录权限(使用统一Web组:$WEB_GROUP)" echo "统一组权限模式:所有Web用户通过组继承权限" # 检测统一组是否存在 if getent group "$WEB_GROUP" &>/dev/null; then echo "使用统一Web组: $WEB_GROUP" WEB_GROUP_GID=$(getent group "$WEB_GROUP" | cut -d: -f3) echo "统一组GID: $WEB_GROUP_GID" else echo "❌ 统一Web组 $WEB_GROUP 不存在,回退到传统模式" WEB_GROUP="www-data" fi # 设置所有权为统一Web组(关键:只管理一个组的权限) echo "设置应用目录所有权为统一Web组" CURRENT_USER=$(whoami) chown -R $CURRENT_USER:$WEB_GROUP "$APP_ROOT" 2>/dev/null || echo "设置所有权失败" # 设置目录权限为775(组权限为rwx,所有组内用户都有完整权限) echo "设置目录权限775,文件权限664" find "$APP_ROOT" -type d -exec chmod 775 {} \; find "$APP_ROOT" -type f -exec chmod 664 {} \; find "$APP_ROOT" -type d -exec chmod g+s {} \; echo "✅ 统一组权限设置完成,所有Web用户通过组获得权限" # 设置ACL(如果支持,只需设置统一组) if command -v setfacl >/dev/null 2>&1; then echo "设置ACL权限(只需设置统一Web组)" # 只为统一Web组设置ACL权限 setfacl -R -m g:$WEB_GROUP:rwx "$APP_ROOT" 2>/dev/null || echo "为统一组 $WEB_GROUP 设置ACL失败" setfacl -dR -m g:$WEB_GROUP:rwx "$APP_ROOT" 2>/dev/null || echo "为统一组 $WEB_GROUP 设置默认ACL失败" echo "✅ 统一组ACL设置完成,所有组内用户自动获得权限" else echo "ACL不支持,依赖传统权限模式" echo "✅ 775权限已足够,所有组内用户都有rwx权限" fi # 设置umask umask 0002 echo "✅ 应用目录权限修复完成" # 验证文件权限是否足够(测试统一组权限效果) echo "=== 验证统一组权限效果 ===" test_file="$APP_ROOT/index.php" if [ -f "$test_file" ]; then echo "测试文件: $test_file" echo "文件权限: $(stat -c '%a %n' "$test_file")" echo "文件所有者: $(stat -c '%U:%G' "$test_file")" # 测试所有Web用户的权限(通过组权限) for test_user in "www-data" "www" "apache" "nginx"; do if id "$test_user" &>/dev/null; then echo "测试 $test_user 用户权限(通过组权限):" # 显示用户组信息 user_groups=$(id -Gn "$test_user" | tr ' ' ',') echo " 所属组: $user_groups" # 测试读权限 if su -s /bin/sh -c "cat '$test_file' >/dev/null 2>&1" "$test_user" 2>/dev/null; then echo " 读权限: ✅ 通过组权限可读" else echo " 读权限: ❌ 不可读" fi # 测试写权限 if su -s /bin/sh -c "echo 'test' >> '$test_file.test' 2>/dev/null && rm '$test_file.test' 2>/dev/null" "$test_user" 2>/dev/null; then echo " 写权限: ✅ 通过组权限可写" else echo " 写权限: ❌ 不可写" fi # 测试目录创建权限 if su -s /bin/sh -c "mkdir -p '$APP_ROOT/test_dir_$test_user' 2>/dev/null && rm -rf '$APP_ROOT/test_dir_$test_user'" "$test_user" 2>/dev/null; then echo " 创建目录: ✅ 通过组权限可创建" else echo " 创建目录: ❌ 不可创建" fi echo " 权限来源: 统一Web组 ($WEB_GROUP) 775权限" break # 只测试第一个可用的用户即可验证效果 fi done else echo "测试文件不存在,尝试创建测试文件" echo '' > "$APP_ROOT/test.php" chown www-data:webaccess "$APP_ROOT/test.php" chmod 664 "$APP_ROOT/test.php" echo "已创建测试文件: $APP_ROOT/test.php" fi # 显示统一组和用户状态 echo "=== 统一Web组状态检查 ===" if getent group "$WEB_GROUP" &>/dev/null; then echo "✅ 统一Web组 '$WEB_GROUP' 存在" echo "组信息: $(getent group $WEB_GROUP)" # 检查哪些用户在统一组中 echo "统一组成员检查:" for web_user in "www-data" "www" "apache" "nginx"; do if id "$web_user" &>/dev/null; then if id -Gn "$web_user" | grep -q "$WEB_GROUP"; then echo "✅ $web_user 在统一组 '$WEB_GROUP' 中" else echo "❌ $web_user 不在统一组 '$WEB_GROUP' 中" fi else echo "❌ $web_user 用户不存在" fi done else echo "❌ 统一Web组 '$WEB_GROUP' 不存在" fi fi echo "=== 启动应用 ===" # 执行原有的启动命令 exec "$@"