nginx日志归档压缩失败的关键在于权限上下文:logrotate以root身份运行,需确保gzip命令可执行、日志目录可写、配置文件可读且未被覆盖,通过logrotate -d和-f 2>&1 | tee调试可精准定位permission denied或command not found等真实错误。

排查 Nginx 归档日志压缩脚本因执行权限不足导致定时任务失败,关键不是看脚本“能不能跑”,而是确认它“以谁的身份、在什么上下文里跑、有没有对应路径和文件的权限”。logrotate 本身不直接执行压缩命令(如 gzip),而是调用系统命令;如果这些命令或目标目录权限不对,就会静默失败——错误日志可能只写一句“gzip: command not found”或“Permission denied”,但实际根源常被忽略。
确认 logrotate 是否真在运行且读取了你的配置
很多人误以为写了 /etc/logrotate.d/nginx 就万事大吉。先验证 logrotate 是否按预期加载该配置:
- 运行 logrotate -d /etc/logrotate.conf(-d 表示 debug 模式),它会模拟执行并打印所有匹配的日志文件、触发条件、执行动作,重点看输出中是否包含你的 Nginx 日志路径(如 /var/log/nginx/*.log)以及是否列出 compress 指令
- 检查 ls -l /etc/logrotate.d/nginx:文件需至少对 root 可读(通常 -rw-r--r-- 即可),若属主不是 root 或权限为 600 以外的受限模式,logrotate 可能跳过该文件
- 确认该文件没被其他规则覆盖:logrotate 按字母顺序读取 /etc/logrotate.d/ 下文件,若存在 nginx-old、nginx2 等命名靠前的同名冲突配置,可能导致你的规则未生效
定位压缩环节卡在哪一步
logrotate 的 compress 动作默认调用 /bin/gzip。失败常见于三类权限断点:
- gzip 命令不可访问:检查 which gzip 输出路径,再运行 ls -l $(which gzip),确保它是可执行文件(权限含 x),且所在目录(如 /bin)对运行 logrotate 的用户(通常是 root)可进入(x 权限)
- 归档目录无写入权:logrotate 默认把压缩后文件放在原日志同一目录,比如 /var/log/nginx/access.log.1.gz。确认 ls -ld /var/log/nginx 返回的权限含 w(如 drwxr-xr-x),且属组/属主允许 root 写入;若目录属 nginx 用户且无 group 写权限,而 logrotate 以 root 运行,仍可写;但若目录被 setgid 或 ACL 限制,就可能失败
- 日志文件本身被锁定或权限异常:Nginx 主进程以 nginx 用户打开日志文件,但 logrotate 以 root 身份重命名它们。只要文件属主是 root 或有 world-writable 权限(不推荐),通常没问题;但如果日志文件权限是 600 且属主不是 root,logrotate 可能无法 rename —— 此时应检查 Nginx 启动用户是否与 logrotate 执行用户冲突(例如 Nginx 用 nginx 用户写日志,但 logrotate 配置里用了 create 600 nginx nginx,却忘了 chmod +x 对目录)
复现并捕获真实错误输出
crond 每天只跑一次 logrotate,失败不易察觉。手动触发并重定向 stderr 是最直接方式:
- 执行 logrotate -f /etc/logrotate.d/nginx 2>&1 | tee /tmp/logrotate-debug.log(-f 强制执行,即使未到轮转周期)
- 查看 /tmp/logrotate-debug.log,重点关注类似 “error: Compressing log /var/log/nginx/error.log.1 failed: gzip returned error code 1” 或 “cannot rename … Permission denied” 的行
- 若看到 “gzip: command not found”,说明 PATH 环境变量在 crond 上下文中不包含 /bin;可在 /etc/logrotate.d/nginx 头部加 su root root 并显式指定 compresscmd,例如:
compresscmd /bin/gzip
compressoptions -9
检查 cron 环境与用户上下文
logrotate 由系统级 crond 触发,其环境变量极简,PATH 通常只有 /usr/bin:/bin,不包含 /usr/local/bin。若你自编译安装了 gzip 或用了非标压缩工具(如 pigz),必须在配置中明确指定路径:
- 在 /etc/logrotate.d/nginx 中添加:
su root root
compresscmd /usr/local/bin/pigz
compressoptions -p4 - 确认该用户(root)对 compresscmd 路径有执行权限:sudo -u root /usr/local/bin/pigz --version 应成功返回
- 避免在配置里写 shell 函数或管道,logrotate 不支持复杂语法;所有压缩逻辑必须由单个可执行二进制完成











