先运行sestatus确认SELinux是否启用并处于enforcing模式;若启用,用ausearch查AVC拒绝日志,ls -Z检查日志文件上下文是否为httpd_log_t,再用semanage fcontext和restorecon修复,最后setenforce 0临时验证。
先检查系统是否启用了 SELinux,因为只有在 enforcing 或 permissive 模式下才可能产生策略拦截。运行以下命令:
sestatus
如果输出中 Current mode: 显示为 enforcing,说明 SELinux 正在强制执行策略;若为 disabled,则问题与 SELinux 无关,可跳过后续步骤。
SELinux 拒绝行为会被记录在 /var/log/audit/audit.log(需 auditd 运行)或通过 dmesg 输出。常用排查方式如下:
典型拒绝信息类似:
type=AVC msg=audit(1712345678.123:456): avc:denied{ write } forpid=1234 comm="nginx" name="access.log" dev="sda1" ino=98765 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file
其中关键字段:scontext 是 Nginx 进程的 SELinux 上下文,tcontext 是目标文件(如日志)的上下文,tclass=file 和 denied { write } 表明写入被拒。
Nginx 默认运行在 httpd_t 域,它只被允许向特定类型(如 httpd_log_t)的文件执行读写操作。使用以下命令查看日志文件当前上下文:
ls -Z /var/log/nginx/access.log
正常应显示类似:
unconfined_u:object_r:httpd_log_t:s0 /var/log/nginx/access.log
如果显示的是 default_t、var_log_t 或其他非 httpd_log_t 类型,就极可能是上下文不匹配导致被拒。
修复方法(临时生效):
sudo semanage fcontext -a -t httpd_log_t "/var/log/nginx(/.*)?"
sudo restorecon -Rv /var/log/nginx
注意:semanage 需要 policycoreutils-python-utils 包支持(RHEL/CentOS 8+ 或 Rocky/AlmaLinux 中为 policycoreutils-python-utils;旧版为 policycoreutils-python)。
执行 restorecon 后,再次运行 ls -Z 确认上下文已更新为 httpd_log_t。然后重启 Nginx:
sudo systemctl restart nginx
观察是否仍报错。如仍有问题,可临时将 SELinux 切为 permissive 模式验证是否为 SELinux 导致:
sudo setenforce 0(仅测试,勿长期使用)
若此时 Nginx 日志写入正常,基本可锁定是 SELinux 策略问题。
如需进一步分析策略缺失,可用:
sudo audit2why -a(解析所有 AVC 拒绝)
或生成自定义模块:
sudo audit2allow -a -M nginx_log_fix && sudo semodule -i nginx_log_fix.pp