diff --git a/docker/php/entrypoint.sh b/docker/php/entrypoint.sh index d3c4b55fa..d952a308b 100644 --- a/docker/php/entrypoint.sh +++ b/docker/php/entrypoint.sh @@ -9,7 +9,8 @@ APP_ROOT="${PHP_APP_ROOT:-/var/www/html}" echo "使用应用根目录: $APP_ROOT" # 创建统一的Web组并配置所有用户(最高效的权限管理) -configure_web_users() { +# 错误处理:如果配置失败,不要终止整个脚本 +configure_web_users || echo "⚠️ Web用户配置出现问题,但继续执行权限设置"() { # 常见Web服务器用户列表 WEB_USERS=("www-data" "www" "apache" "nginx") @@ -19,73 +20,199 @@ configure_web_users() { echo "配置统一Web组权限,目标UID:GID = $TARGET_UID:$TARGET_GID" - # 创建统一的Web组 + # 创建统一的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 组失败" + + # 尝试使用指定GID创建组 + if groupadd -g $TARGET_GID "$WEB_GROUP" 2>/dev/null; then + echo "✅ 统一Web组创建成功,GID: $TARGET_GID" + else + echo "⚠️ GID $TARGET_GID 已被占用,尝试自动分配GID" + + # 尝试不指定GID创建组 + if groupadd "$WEB_GROUP" 2>/dev/null; then + ACTUAL_GID=$(getent group "$WEB_GROUP" | cut -d: -f3) + echo "✅ 统一Web组创建成功,自动分配GID: $ACTUAL_GID" + else + echo "❌ 创建 $WEB_GROUP 组失败,尝试使用备用方案" + + # 备用方案:使用现有的www-data组 + if getent group "www-data" &>/dev/null; then + WEB_GROUP="www-data" + echo "🔄 使用现有的www-data组作为统一组" + else + echo "❌ 备用方案也失败,权限配置可能不完整" + WEB_GROUP="" + fi + fi + fi else - echo "统一Web组 $WEB_GROUP 已存在" + ACTUAL_GID=$(getent group "$WEB_GROUP" | cut -d: -f3) + echo "✅ 统一Web组 $WEB_GROUP 已存在,GID: $ACTUAL_GID" fi - # 只将已存在的Web用户加入统一组(不创建新用户) + # 最终验证组是否存在 + if [ -z "$WEB_GROUP" ] || ! getent group "$WEB_GROUP" &>/dev/null; then + echo "❌ 无法创建或找到可用的Web组,权限配置将受限" + return 1 + fi + + # 只将已存在的Web用户加入统一组(增强错误处理) + success_count=0 + total_users=0 + for web_user in "${WEB_USERS[@]}"; do + total_users=$((total_users + 1)) + 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 失败" + echo "📝 处理Web用户: $web_user" + + # 获取用户当前组信息 + current_groups=$(id -Gn "$web_user" 2>/dev/null | tr ' ' ',') + echo " 当前所属组: $current_groups" + + # 尝试将用户加入统一组(使用-a参数保留现有组,只添加新组) + if usermod -a -G "$WEB_GROUP" "$web_user" 2>/dev/null; then + echo " ✅ 成功将 $web_user 添加到统一组 $WEB_GROUP" + success_count=$((success_count + 1)) + else + echo " ⚠️ 无法将 $web_user 添加到统一组,尝试设置主组" + + # 备用方案:设置主组 + if usermod -g "$WEB_GROUP" "$web_user" 2>/dev/null; then + echo " ✅ 成功将 $web_user 主组设置为 $WEB_GROUP" + success_count=$((success_count + 1)) + else + echo " ❌ 无法配置 $web_user 的组权限" + fi + fi else - echo "Web用户 $web_user 不存在,跳过" + echo "⚭ Web用户 $web_user 不存在,跳过" fi done + echo "📊 用户配置汇总: $success_count/$total_users 个Web用户配置成功" + + # 至少要有一个用户配置成功 + if [ $success_count -eq 0 ]; then + echo "⚠️ 没有Web用户被成功配置,但继续执行" + fi + echo "统一Web组配置完成" } -configure_web_users +# 错误处理:如果配置失败,不要终止整个脚本 +configure_web_users || echo "⚠️ Web用户配置出现问题,但继续执行权限设置" echo "当前用户: $(whoami)" echo "UID: $(id -u), GID: $(id -g)" # 修复所有目录权限(使用统一Web组,最高效的权限管理) if [ -d "$APP_ROOT" ]; then - WEB_GROUP="webaccess" - echo "修复应用目录权限(使用统一Web组:$WEB_GROUP)" - echo "统一组权限模式:所有Web用户通过组继承权限" + # 重新获取最终的WEB_GROUP(可能已被修改) + FINAL_WEB_GROUP="" - # 检测统一组是否存在 - 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" + # 首选:使用创建的webaccess组 + if getent group "webaccess" &>/dev/null; then + FINAL_WEB_GROUP="webaccess" + echo "🎯 使用创建的统一Web组: $FINAL_WEB_GROUP" + # 备选:使用www-data组 + elif getent group "www-data" &>/dev/null; then + FINAL_WEB_GROUP="www-data" + echo "🔄 回退到www-data组: $FINAL_WEB_GROUP" + # 最后:使用当前用户的组 else - echo "❌ 统一Web组 $WEB_GROUP 不存在,回退到传统模式" - WEB_GROUP="www-data" + CURRENT_USER=$(whoami) + CURRENT_GROUP=$(id -gn "$CURRENT_USER") + FINAL_WEB_GROUP="$CURRENT_GROUP" + echo "🔧 使用当前用户组: $FINAL_WEB_GROUP" fi - # 设置所有权为统一Web组(关键:只管理一个组的权限) - echo "设置应用目录所有权为统一Web组" + # 最终验证 + if [ -z "$FINAL_WEB_GROUP" ]; then + echo "❌ 无法确定有效的Web组,跳过权限设置" + return 1 + fi + + WEB_GROUP="$FINAL_WEB_GROUP" + WEB_GROUP_GID=$(getent group "$WEB_GROUP" | cut -d: -f3) + echo "✅ 最终使用Web组: $WEB_GROUP (GID: $WEB_GROUP_GID)" + echo "🔒 统一组权限模式:所有Web用户通过组继承权限" + + # 设置所有权为统一Web组(增强错误处理) + echo "📁 设置应用目录所有权为统一Web组" CURRENT_USER=$(whoami) - chown -R $CURRENT_USER:$WEB_GROUP "$APP_ROOT" 2>/dev/null || echo "设置所有权失败" + + if chown -R $CURRENT_USER:$WEB_GROUP "$APP_ROOT" 2>/dev/null; then + echo "✅ 所有权设置成功: $CURRENT_USER:$WEB_GROUP" + else + echo "⚠️ 所有权设置失败,尝试只设置组权限" + chgrp -R "$WEB_GROUP" "$APP_ROOT" 2>/dev/null || echo "❌ 组权限设置也失败" + fi # 设置目录权限为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 "🔐 设置目录权限775,文件权限664" + + # 使用更安全的权限设置方式,避免权限被拒绝 + dir_count=0 + file_count=0 + + # 设置目录权限 + while IFS= read -r -d '' dir; do + if chmod 775 "$dir" 2>/dev/null; then + dir_count=$((dir_count + 1)) + fi + done < <(find "$APP_ROOT" -type d -print0 2>/dev/null | head -z -1000) # 限制处理数量避免性能问题 + + # 设置文件权限 + while IFS= read -r -d '' file; do + if chmod 664 "$file" 2>/dev/null; then + file_count=$((file_count + 1)) + fi + done < <(find "$APP_ROOT" -type f -print0 2>/dev/null | head -z -1000) + + # 设置setgid位,确保新文件继承组权限 + while IFS= read -r -d '' dir; do + chmod g+s "$dir" 2>/dev/null + done < <(find "$APP_ROOT" -type d -print0 2>/dev/null | head -z -500) + + echo "📊 权限设置完成: $dir_count个目录, $file_count个文件" echo "✅ 统一组权限设置完成,所有Web用户通过组获得权限" # 设置ACL(如果支持,只需设置统一组) if command -v setfacl >/dev/null 2>&1; then - echo "设置ACL权限(只需设置统一Web组)" + 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失败" + acl_success=0 - echo "✅ 统一组ACL设置完成,所有组内用户自动获得权限" + # 只为统一Web组设置ACL权限(限制处理深度) + if setfacl -R -m g:$WEB_GROUP:rwx "$APP_ROOT" 2>/dev/null; then + echo " ✅ 设置组ACL权限成功" + acl_success=$((acl_success + 1)) + else + echo " ❌ 设置组ACL权限失败" + fi + + # 设置默认ACL权限(新创建的文件自动继承权限) + if setfacl -dR -m g:$WEB_GROUP:rwx "$APP_ROOT" 2>/dev/null; then + echo " ✅ 设置默认ACL权限成功" + acl_success=$((acl_success + 1)) + else + echo " ❌ 设置默认ACL权限失败" + fi + + if [ $acl_success -eq 2 ]; then + echo "🎉 统一组ACL设置完成,所有组内用户自动获得权限" + elif [ $acl_success -eq 1 ]; then + echo "⚠️ ACL部分设置成功,建议检查文件系统ACL支持" + else + echo "❌ ACL设置完全失败,文件系统可能不支持ACL" + fi else - echo "ACL不支持,依赖传统权限模式" + echo "ℹ️ ACL不支持,依赖传统权限模式" echo "✅ 775权限已足够,所有组内用户都有rwx权限" fi