237 lines
6.8 KiB
Bash
237 lines
6.8 KiB
Bash
#!/bin/bash
|
||
set -e
|
||
|
||
echo "=== ThinkPHP Docker权限初始化 ==="
|
||
|
||
# 定义应用根目录,优先使用环境变量,否则使用默认值
|
||
APP_ROOT="${PHP_APP_ROOT:-/var/www/html}"
|
||
|
||
echo "使用应用根目录: $APP_ROOT"
|
||
|
||
# 获取正确的用户和组
|
||
if [ -n "$USER_ID" ] && [ -n "$GROUP_ID" ]; then
|
||
# 如果指定了用户ID,修改www-data
|
||
usermod -u $USER_ID www-data
|
||
groupmod -g $GROUP_ID www-data
|
||
fi
|
||
|
||
echo "当前用户: $(whoami)"
|
||
echo "UID: $(id -u), GID: $(id -g)"
|
||
|
||
# 修复目录所有权和权限
|
||
fix_directory_permissions() {
|
||
local dir=$1
|
||
echo "修复PHP目录权限: $dir"
|
||
|
||
# 确保目录存在
|
||
mkdir -p "$dir"
|
||
|
||
# 设置所有权
|
||
chown -R www-data:www-data "$dir"
|
||
|
||
# 设置权限
|
||
chmod -R 775 "$dir"
|
||
|
||
# 设置setgid权限
|
||
chmod g+s "$dir"
|
||
|
||
# 尝试设置ACL(如果支持)
|
||
if command -v setfacl >/dev/null 2>&1; then
|
||
setfacl -dR -m u:www-data:rwx "$dir"
|
||
fi
|
||
|
||
find "$dir" -type d -exec chmod 775 {} \;
|
||
find "$dir" -type f -exec chmod 775 {} \;
|
||
find "$dir" -type d -exec chmod g+s {} \;
|
||
find "$dir" -type f -exec chmod g+s {} \;
|
||
|
||
# 设置umask
|
||
umask 0002
|
||
|
||
echo "✅ $dir 权限设置完成, 目录权限: $(stat -c '%a %n' "$dir"), setgid权限: $(stat -c '%a %n' "$dir" | grep 's')"
|
||
}
|
||
|
||
|
||
# 处理所有需要权限的目录
|
||
directories=("addon" "app" "config" "extend" "public" "runtime" "upload" "runtime/log" "runtime/cache" "runtime/temp")
|
||
for dir in "${directories[@]}"; do
|
||
fix_directory_permissions "$APP_ROOT/$dir"
|
||
done
|
||
|
||
|
||
# 验证权限
|
||
echo "=== 权限验证 ==="
|
||
echo "当前用户: $(whoami)"
|
||
echo "当前UID: $(id -u), GID: $(id -g)"
|
||
echo "当前umask: $(umask)"
|
||
|
||
# 验证www-data用户是否可以在runtime和upload目录下新建子目录
|
||
|
||
# 方法1:使用sudo
|
||
if command -v sudo >/dev/null 2>&1; then
|
||
echo "使用sudo测试..."
|
||
if sudo -u www-data mkdir -p $APP_ROOT/runtime/log/test_dir 2>/dev/null; then
|
||
echo "✅ sudo: runtime目录创建子目录成功 [使用www-data用户]"
|
||
rm -rf $APP_ROOT/runtime/log/test_dir
|
||
else
|
||
echo "❌ sudo: runtime目录创建子目录失败 [使用www-data用户]"
|
||
fi
|
||
fi
|
||
|
||
# 方法2:使用su
|
||
echo "使用su测试..."
|
||
if su -s /bin/sh -c "mkdir -p $APP_ROOT/runtime/log/test_dir" www-data 2>/dev/null; then
|
||
echo "✅ su: runtime目录创建子目录成功 [使用www-data用户]"
|
||
rm -rf $APP_ROOT/runtime/log/test_dir
|
||
else
|
||
echo "❌ su: runtime目录创建子目录失败 [使用www-data用户]"
|
||
fi
|
||
|
||
# 方法3:使用runuser
|
||
if command -v runuser >/dev/null 2>&1; then
|
||
echo "使用runuser测试..."
|
||
if runuser -u www-data -- mkdir -p $APP_ROOT/runtime/log/test_dir 2>/dev/null; then
|
||
echo "✅ runuser: runtime目录创建子目录成功 [使用www-data用户]"
|
||
rm -rf $APP_ROOT/runtime/log/test_dir
|
||
else
|
||
echo "❌ runuser: runtime目录创建子目录失败 [使用www-data用户]"
|
||
fi
|
||
fi
|
||
|
||
# 检查www-data用户和组
|
||
echo "检查www-data用户..."
|
||
id www-data
|
||
groups www-data
|
||
|
||
# 检查目录的实际权限
|
||
echo "检查目录权限..."
|
||
for dir in "${directories[@]}"; do
|
||
echo "检查目录权限: $dir"
|
||
ls -ld "$APP_ROOT/$dir"
|
||
done
|
||
|
||
echo "检查setgid权限..."
|
||
for dir in "${directories[@]}"; do
|
||
echo "检查setgid权限: $dir"
|
||
stat -c '%a %n' "$APP_ROOT/$dir" | grep 's'
|
||
done
|
||
|
||
echo "=== 检测 PHP 执行用户 ==="
|
||
|
||
# 检查命令可用性函数
|
||
command_exists() {
|
||
command -v "$1" >/dev/null 2>&1
|
||
}
|
||
|
||
# 方法1:通过 PHP 脚本检测当前用户
|
||
echo "方法1: 通过 PHP 检测当前执行用户"
|
||
if command_exists php; then
|
||
php -r "
|
||
if (function_exists('get_current_user')) {
|
||
echo '当前 PHP 执行用户: ' . get_current_user() . PHP_EOL;
|
||
} else {
|
||
echo 'get_current_user() 函数不可用' . PHP_EOL;
|
||
}
|
||
|
||
if (function_exists('getmyuid')) {
|
||
echo '当前用户 ID: ' . getmyuid() . PHP_EOL;
|
||
} else {
|
||
echo 'getmyuid() 函数不可用' . PHP_EOL;
|
||
}
|
||
|
||
if (function_exists('getmygid')) {
|
||
echo '当前组 ID: ' . getmygid() . PHP_EOL;
|
||
} else {
|
||
echo 'getmygid() 函数不可用' . PHP_EOL;
|
||
}
|
||
|
||
if (function_exists('posix_geteuid') && function_exists('posix_getpwuid')) {
|
||
echo '当前进程用户: ' . posix_getpwuid(posix_geteuid())['name'] . PHP_EOL;
|
||
} else {
|
||
echo 'posix 函数不可用,尝试系统方法' . PHP_EOL;
|
||
echo '当前用户: ' . exec('whoami') . PHP_EOL;
|
||
}
|
||
" 2>/dev/null || echo "PHP 执行检测失败"
|
||
else
|
||
echo "❌ PHP 命令不可用,跳过检测"
|
||
fi
|
||
|
||
# 方法2:通过进程检测 PHP-FPM 运行用户
|
||
echo "方法2: 检测 PHP-FPM 进程用户"
|
||
if command_exists pgrep; then
|
||
if pgrep php-fpm > /dev/null 2>&1; then
|
||
if command_exists ps; then
|
||
ps aux | grep php-fpm | grep -v grep | head -3 2>/dev/null || echo "进程检测失败"
|
||
else
|
||
echo "ps 命令不可用,但找到 PHP-FPM 进程"
|
||
fi
|
||
else
|
||
echo "PHP-FPM 进程未运行"
|
||
fi
|
||
else
|
||
echo "pgrep 命令不可用,尝试其他方法"
|
||
if command_exists ps; then
|
||
echo "使用 ps 直接检测:"
|
||
ps aux | grep php-fpm | grep -v grep | head -3 2>/dev/null || echo "未找到 PHP-FPM 进程"
|
||
else
|
||
echo "ps 和 pgrep 命令都不可用,无法检测进程"
|
||
fi
|
||
fi
|
||
|
||
# 方法3:检测配置文件中的用户设置
|
||
echo "方法3: 检查配置文件中的用户设置"
|
||
|
||
# PHP-FPM 配置检查
|
||
php_fpm_configs=(
|
||
"/usr/local/etc/php-fpm.d/www.conf"
|
||
"/etc/php-fpm.d/www.conf"
|
||
"/usr/local/etc/php-fpm.conf"
|
||
"/etc/php-fpm.conf"
|
||
)
|
||
|
||
for config_file in "${php_fpm_configs[@]}"; do
|
||
if [ -f "$config_file" ]; then
|
||
echo "找到 PHP-FPM 配置: $config_file"
|
||
if command_exists grep; then
|
||
echo "PHP-FPM 用户配置:"
|
||
grep -E "^user|^group" "$config_file" 2>/dev/null || echo "未找到用户配置行"
|
||
else
|
||
echo "grep 命令不可用,但配置文件存在"
|
||
fi
|
||
break
|
||
fi
|
||
done
|
||
|
||
# Nginx 配置检查
|
||
nginx_configs=(
|
||
"/etc/nginx/nginx.conf"
|
||
"/usr/local/nginx/conf/nginx.conf"
|
||
"/etc/nginx/conf/nginx.conf"
|
||
)
|
||
|
||
for config_file in "${nginx_configs[@]}"; do
|
||
if [ -f "$config_file" ]; then
|
||
echo "找到 Nginx 配置: $config_file"
|
||
if command_exists grep; then
|
||
echo "Nginx 用户配置:"
|
||
grep -E "^user" "$config_file" 2>/dev/null || echo "未找到用户配置行"
|
||
else
|
||
echo "grep 命令不可用,但配置文件存在"
|
||
fi
|
||
break
|
||
fi
|
||
done
|
||
|
||
# 方法4:使用 /proc 文件系统检测(如果其他方法都失败)
|
||
echo "方法4: 使用 /proc 文件系统检测"
|
||
if [ -d "/proc" ]; then
|
||
echo "当前脚本执行用户: $(whoami 2>/dev/null || echo 'whoami 命令不可用')"
|
||
echo "当前脚本用户 ID: $(id -u 2>/dev/null || echo 'id 命令不可用')"
|
||
else
|
||
echo "/proc 目录不可用"
|
||
fi
|
||
|
||
echo "=== 启动应用 ==="
|
||
|
||
# 执行原有的启动命令
|
||
exec "$@" |