今天读了一篇文章《谈谈nginx信号集》
感兴趣的同学可以查看此链接 http://io.upyun.com/2017/08/19/nginx-signals/
因为知识有限, 其中有段话不是很理解, 最后咨询才了解原来如此, 希望能对大家有些帮助。
master 进程收到 SIGUSR1 后,会重新打开所有已经打开的文件(比如日志),然后向每个 worker 进程发送 SIGUSR1 信息,worker 进程收到信号后,会执行同样的操作。reopen 可用于日志切割,比如 NGINX 官方就提供了一个方案:
$ mv access.log access.log.0
$ kill -USR1 `cat master.nginx.pid` # 重新打开日志文件
$ sleep 1
$ gzip access.log.0 # do something with access.log.0
这里 sleep 1 是必须的,因为在 master 进程向 worker 进程发送 SIGUSR1 消息到 worker 进程真正重新打开 access.log 之间,有一段时间窗口,此时 worker 进程还是向文件 access.log.0 里写入日志的。通过 sleep 1s,保证了 access.log.0 日志信息的完整性(如果没有 sleep 而直接进行压缩,很有可能出现日志丢失的情况)。
看到这段话不懂知识的我眼泪掉下来
问: 我理解的是worker一直会在access.log里面写,为什么又写到新文件名 access.log.0 呢
mv 只是在文件系统层面把 access.log 重命名成了 access.log.0 如果这个时候有进程打开着 access.log,重命名后就会向 access.log.0,本质上 fd 指向的文件是同一个 代码层面,文件的标识符是文件句柄 fd 所以需要让 nginx 重新 close,open 这个 access.log,才会开始写新的文件
所以呢,sleep 1;是很有必要的, 可以尽量避免切换日志文件(实际是切换fd)过程中,日志的丢失