logrotate报错permission denied主因是日志父目录权限不当或新文件属主错误,需检查/var/log/nginx/目录权限并配置create 644 www-data www-data确保nginx可写,同时排除journald、selinux/apparmor干扰。

直接改 logrotate 配置或强制用 root 轮转日志,大概率会引发新权限问题——真正要动的是轮转后日志文件的属主和 umask,而不是绕过权限检查。
logrotate 执行时提示 (13: Permission denied)
这类报错不是 logrotate 本身没权限运行,而是它在重命名、创建新日志或压缩旧日志时,被目标目录拒绝写入。典型表现是:
error: error creating output file /var/log/nginx/access.log.1: Permission deniederror: skipping "/var/log/nginx/error.log" because parent directory has insecure permissions (It's world writable or not owned by root)
关键线索在报错里提到的路径和“parent directory”——logrotate 默认要求日志父目录(如 /var/log/nginx/)不能是 world-writable,且必须由 root 或配置中指定用户拥有。
检查方式:
ls -ld /var/log/nginx/
如果输出含 drwxrwxrwx 或 drwxrwxr-x 且属组不是 root,就触发了安全拒绝。
nginx 日志轮转后新文件属主不对
即使 logrotate 成功切分,新生成的 access.log 和 error.log 常常属于 root,而 Nginx worker 进程(比如以 www-data 身份运行)无法继续写入,导致后续请求日志丢失、甚至触发 500 错误。
根本原因在于 logrotate 默认不保留原文件属主,也不自动适配 Nginx 运行用户。
修复要点:
- 在
/etc/logrotate.d/nginx配置中显式添加create 644 www-data www-data(把www-data换成你实际的 Nginx 用户) - 确保
rotate前的旧日志(如access.log.1)不干扰:它们可以归档为root,但新日志必须可写 - 避免使用
copytruncate代替create——它不解决属主问题,还可能丢最后一段日志
systemd-journald 干扰 nginx 日志写入
某些系统(尤其较新 Debian/Ubuntu)默认启用 journald 捕获 stdout/stderr,若 Nginx 配置了 error_log stderr 或未指定日志路径,logrotate 就可能根本找不到目标文件,或轮转后 journald 继续往旧 inode 写,造成混乱。
确认是否被接管:
systemctl show nginx | grep StandardError
如果输出类似 StandardError=journal,说明日志正走 journald。此时应:
- 要么在
/etc/nginx/nginx.conf中明确指定error_log /var/log/nginx/error.log warn;(并确保路径存在、权限正确) - 要么停用 journald 接管:
sudo systemctl edit nginx,写入:[Service] StandardError=file:/var/log/nginx/error.log
再
sudo systemctl daemon-reload && sudo systemctl restart nginx
SELinux 或 AppArmor 拦截 logrotate 操作
在启用 SELinux 的系统(如 CentOS/RHEL)上,logrotate 默认策略可能不允许它修改 Nginx 日志目录上下文,尤其当目录被标记为 httpd_log_t 以外类型时。
验证方式:
ausearch -m avc -ts recent | grep logrotate
若看到 avc: denied { write },说明被拦截。临时放行(仅用于验证):
sudo setsebool -P logrotate_read_httpd_log on
更稳妥做法是恢复目录上下文:
sudo restorecon -Rv /var/log/nginx/
注意:AppArmor 用户需检查 /etc/apparmor.d/usr.sbin.nginx 是否允许 /var/log/nginx/** rw, 规则。
最易被忽略的一点:logrotate 配置里的 sharedscripts 和 postrotate 脚本若调用了 nginx -s reopen,该命令必须由 Nginx worker 实际用户能执行——否则 reopen 失败,新日志仍不会被写入,而错误却静默消失。











