chore(docker): 优化docker/php/entrypoint.sh

This commit is contained in:
2025-12-25 14:22:59 +08:00
parent c7aaa1bd16
commit 85cf52b0e4

View File

@@ -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'
<!DOCTYPE html>
<html>
<head><title>Permission Test</title></head>
<body><h1>Web Server Permission Test File</h1></body>
</html>
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 '<?php echo "test"; ?>' > "$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 "统一组成员检查:"