Nginx 的 access_log 不支持 %Y%m%d 等 strftime 格式符,因其路径解析仅接受静态路径或命名管道,不执行时间变量替换;直接使用会导致启动报错“invalid number of arguments”。

cronolog 不是 Nginx 内置组件,必须手动安装并配合命名管道使用;直接写 access_log /path/access_%Y%m%d.log 是无效的。
为什么不能直接在 access_log 指令里用时间变量?
Nginx 的 access_log 路径不支持 %Y、%m 这类 strftime 格式符 —— 它只接受静态路径或命名管道(fifo)。试图写成 access_log /var/log/nginx/access_%Y%m%d.log 会导致启动失败,报错:invalid number of arguments in "access_log" directive。
真正能动态生成带时间戳日志的,是外部程序(如 cronolog)从管道读取原始日志流后,按模板切分写入。
- nginx 只负责往管道里“写”,不关心文件名
-
cronolog负责“读管道 + 解析时间 + 写对应文件” - 二者必须通过
mkfifo建立通信桥梁
安装 cronolog 的两种可靠方式
源码编译更可控,尤其在 CentOS/RHEL 或无 root 权限时;yum 安装快但版本老旧(如 CentOS 7 自带的是 1.6.2,不支持 -z 时区参数)。
- 源码安装(推荐):
wget http://cronolog.org/download/cronolog-1.6.2.tar.gz tar zxvf cronolog-1.6.2.tar.gz cd cronolog-1.6.2 ./configure --prefix=/usr/local/cronolog make && make install ln -s /usr/local/cronolog/sbin/cronolog /usr/bin/cronolog
- yum 安装(仅限有包且满足需求):
yum install -y cronolog,装完检查版本:cronolog -V,若低于 1.6.2,建议换源码
cronolog 启动命令怎么写才不丢日志?
关键点:必须在 nginx 启动前运行 cronolog,否则管道没消费者,nginx 写日志会阻塞甚至夯住。常见错误是先启 nginx、再补跑 cronolog,此时已有日志堆积在管道缓冲区,可能丢失。
- 创建命名管道:
mkfifo /var/log/nginx/access.log_pipe(路径需和access_log配置一致) - 启动
cronolog(后台运行,重定向输出避免挂起):nohup cat /var/log/nginx/access.log_pipe | cronolog /var/log/nginx/access_%Y%m%d%H%M.log > /dev/null 2>&1 &
- 确认进程存活:
ps aux | grep cronolog,看到cat | cronolog管道链才算成功 - 再启动 nginx:
/usr/local/nginx/sbin/nginx
如果 nginx 已运行,可 reload 触发日志 reopen:kill -USR1 $(cat /usr/local/nginx/logs/nginx.pid),但前提是管道已就位,否则 reload 后仍会卡住。
配置 access_log 指向管道时要注意什么?
nginx 配置里必须把 access_log 指向你创建的 fifo 文件,且不能加任何格式修饰(比如 buffer=64k 在管道上无效)。
- 正确写法:
access_log /var/log/nginx/access.log_pipe main; - 错误写法:
access_log /var/log/nginx/access.log_pipe main buffer=64k;(buffer 对管道无意义) - 错误写法:
access_log /var/log/nginx/access_%Y%m%d.log main;(Nginx 不解析时间变量) - 权限要对齐:nginx worker 进程用户(如
www-data或nginx)必须对 fifo 文件有写权限,cronolog进程用户需有目标日志目录写权限
最易忽略的是权限和启动顺序 —— 二者任一出错,都会导致日志静默消失,且无明显报错提示。


















