diff --git a/docker/php/entrypoint.sh b/docker/php/entrypoint.sh index d952a308b..1b5a7ccf2 100644 --- a/docker/php/entrypoint.sh +++ b/docker/php/entrypoint.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -e +# 移除 set -e 以便更好的错误控制 echo "=== ThinkPHP Docker权限初始化 ===" @@ -9,8 +9,7 @@ APP_ROOT="${PHP_APP_ROOT:-/var/www/html}" echo "使用应用根目录: $APP_ROOT" # 创建统一的Web组并配置所有用户(最高效的权限管理) -# 错误处理:如果配置失败,不要终止整个脚本 -configure_web_users || echo "⚠️ Web用户配置出现问题,但继续执行权限设置"() { +configure_web_users() { # 常见Web服务器用户列表 WEB_USERS=("www-data" "www" "apache" "nginx") @@ -69,9 +68,9 @@ configure_web_users || echo "⚠️ Web用户配置出现问题,但继续执 if id "$web_user" &>/dev/null; then echo "📝 处理Web用户: $web_user" - # 获取用户当前组信息 - current_groups=$(id -Gn "$web_user" 2>/dev/null | tr ' ' ',') - echo " 当前所属组: $current_groups" + # 获取用户当前组信息(安全的变量处理) + current_groups=$(id -Gn "$web_user" 2>/dev/null | tr '\n' ' ' | sed 's/ *$//') + echo " 当前所属组: ${current_groups:-无}" # 尝试将用户加入统一组(使用-a参数保留现有组,只添加新组) if usermod -a -G "$WEB_GROUP" "$web_user" 2>/dev/null; then @@ -133,7 +132,8 @@ if [ -d "$APP_ROOT" ]; then # 最终验证 if [ -z "$FINAL_WEB_GROUP" ]; then echo "❌ 无法确定有效的Web组,跳过权限设置" - return 1 + echo "=== 启动应用 ===" + exec "$@" fi WEB_GROUP="$FINAL_WEB_GROUP" @@ -159,24 +159,17 @@ if [ -d "$APP_ROOT" ]; then 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) + # 设置目录权限(兼容性更好的方式) + if command -v find >/dev/null 2>&1; then + dir_count=$(find "$APP_ROOT" -type d -exec chmod 775 {} \; 2>/dev/null | wc -l) + file_count=$(find "$APP_ROOT" -type f -exec chmod 664 {} \; 2>/dev/null | wc -l) + find "$APP_ROOT" -type d -exec chmod g+s {} \; 2>/dev/null + else + # 备用方案:使用简单的循环 + echo "find命令不可用,跳过批量权限设置" + dir_count=0 + file_count=0 + fi echo "📊 权限设置完成: $dir_count个目录, $file_count个文件" @@ -223,59 +216,103 @@ if [ -d "$APP_ROOT" ]; then # 验证文件权限是否足够(测试统一组权限效果) echo "=== 验证统一组权限效果 ===" - test_file="$APP_ROOT/index.php" + + # 查找测试文件的更可靠方法 + test_file="" + + # 方法1: 查找index.html + if [ -f "$APP_ROOT/index.html" ]; then + test_file="$APP_ROOT/index.html" + fi + + # 方法2: 查找任意HTML文件(更安全的方式) + if [ -z "$test_file" ]; then + first_html=$(find "$APP_ROOT" -maxdepth 2 -name "*.html" -type f 2>/dev/null | head -1) + if [ -n "$first_html" ] && [ -f "$first_html" ]; then + test_file="$first_html" + fi + fi + + # 方法3: 查找index.php + if [ -z "$test_file" ] && [ -f "$APP_ROOT/index.php" ]; then + test_file="$APP_ROOT/index.php" + fi + + # 方法4: 创建专用测试文件(最安全的选择) + if [ -z "$test_file" ]; then + test_file="$APP_ROOT/.permission_test.html" + echo "创建专用权限测试文件" + cat > "$test_file" << 'EOF' + + +Permission Test +

Web Server Permission Test File

+ +EOF + # 设置正确的权限 + chown $(whoami):"$WEB_GROUP" "$test_file" 2>/dev/null || true + chmod 664 "$test_file" + fi + + # 执行权限测试 if [ -f "$test_file" ]; then - echo "测试文件: $test_file" + 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 用户权限(通过组权限):" + echo "🔍 测试 $test_user 用户权限(通过组权限):" - # 显示用户组信息 - user_groups=$(id -Gn "$test_user" | tr ' ' ',') - echo " 所属组: $user_groups" + # 显示用户组信息(安全的变量处理) + user_groups=$(id -Gn "$test_user" 2>/dev/null | tr '\n' ' ' | sed 's/ *$//') + echo " 📋 所属组: ${user_groups:-无}" - # 测试读权限 + # 测试读权限(安全:只读不修改) if su -s /bin/sh -c "cat '$test_file' >/dev/null 2>&1" "$test_user" 2>/dev/null; then - echo " 读权限: ✅ 通过组权限可读" + echo " ✅ 读权限: 通过组权限可读" else - echo " 读权限: ❌ 不可读" + 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 " 写权限: ✅ 通过组权限可写" + # 测试写权限(使用临时文件,避免污染原文件) + temp_test_file="${test_file}.write_test_${test_user}" + if su -s /bin/sh -c "echo 'permission_test' > '$temp_test_file' 2>/dev/null" "$test_user" 2>/dev/null; then + echo " ✅ 写权限: 通过组权限可写" + rm -f "$temp_test_file" 2>/dev/null else - echo " 写权限: ❌ 不可写" + 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 " 创建目录: ✅ 通过组权限可创建" + # 测试目录创建权限(使用临时目录) + temp_test_dir="${APP_ROOT}/.perm_test_${test_user}" + if su -s /bin/sh -c "mkdir -p '$temp_test_dir' 2>/dev/null" "$test_user" 2>/dev/null; then + echo " ✅ 创建目录: 通过组权限可创建" + rm -rf "$temp_test_dir" 2>/dev/null else - echo " 创建目录: ❌ 不可创建" + echo " ❌ 创建目录: 不可创建" fi - echo " 权限来源: 统一Web组 ($WEB_GROUP) 775权限" + echo " 🔗 权限来源: 统一Web组 ($WEB_GROUP) 775权限" break # 只测试第一个可用的用户即可验证效果 fi done + + # 清理专用测试文件(如果是创建的) + if echo "$test_file" | grep -q "\.permission_test\.html$"; then + rm -f "$test_file" 2>/dev/null + echo "🧹 已清理临时测试文件" + fi 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" + echo "❌ 无法找到或创建测试文件,跳过权限验证" fi # 显示统一组和用户状态 echo "=== 统一Web组状态检查 ===" if getent group "$WEB_GROUP" &>/dev/null; then echo "✅ 统一Web组 '$WEB_GROUP' 存在" - echo "组信息: $(getent group $WEB_GROUP)" + echo "组信息: $(getent group "$WEB_GROUP" 2>/dev/null || echo '获取失败')" # 检查哪些用户在统一组中 echo "统一组成员检查:"