第12章 Nginx日志

Nginx 日志功能介绍

通常,在生产环境中使用 Nginx 进行反向代理和负载均衡或者各种其他处理时,良好的日志记录是非常关键的一环。通过精心配置的 Nginx 日志,我们可以获取用户的真实 ip、浏览器信息,请求处理时间,请求 URL 等,这样方便我们排查和回溯错误。具体要记录哪些信息,可以通过 Nginx 中的 log_format 指令定义,由它定义日志的格式。而对于使用哪种日志格式和设置日志的保存路径则由access_log 指令指定的。另外在 Nginx 中还有一个配置服务器和请求处理过程中的错误信息的指令,那就是 error_log 指令。最后,如果在配置的日志文件路径中使用了变量,我们可以通过 open_log_file_cache 指令来设置缓存,提升性能。对于大型的网站而言,大量的 http 请求意味着大量的日志记录,及时按天或按大小进行 Nginx 日志备份也至关重要的。
在 Nginx 的日志模块主要有 2 个, ngx_stream_log_module 和ngx_http_log_module,分别表示四层的日志模块和七层的日志模块,其指令和用法都是一致的,接下来我们只针对 http 请求的日志进行说明和使用。

日志相关指令说明

在 ngx_http_log_module 模块中,只 3 个指令,分别是 access_log、log_format 和open_log_file_cache。这些指令具体的格式如下:

Syntax: access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;
Default:    
access_log logs/access.log combined;
Context:    http, server, location, if in location, limit_except
Default:    log_format combined "...";
Context:    http
Syntax: open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];
open_log_file_cache off;
Default:    open_log_file_cache off;
Context:    http, server, location

ngx_http_log_module 模块用来按某个格式来记录请求的日志。模块中的log_format 指令就是用来设置打印日志的格式,该指令中可以使用 Nginx 中的各种变量,比如保存远端 ip 地址的变量$remote_addr 等

   log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                     '$status $body_bytes_sent "$http_referer" '
                     '"$http_user_agent" "$http_x_forwarded_for"';

接下来是 access_log 指令。参考前面的指令格式。关闭日志记录,直接是写access_log off,如果打开 access 日志,它的写法是:

access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];

# path 是指定日志的写入路径,默认写入 logs/access.log 文件中。注意日志路径可以包变量,但是会一些限制。
# format 就是指定打的日志格式,也就是前面 log_format 指令定义好的格式。每个格式会设置一个格式名,这里取对应的格式名称,默认使用预定义的 combined。
# buffer 用来指定日志写入时的缓存大小。默认是 64k。
# gzip 日志写入前先进行压缩。压缩率可以指定,从 1 到 9 数值越大压缩比越高,同时压缩的速度也越慢。默认是 1。
# flush 设置缓存的有效时间。如果超过 flush 指定的时间,缓存中的内容将被清空。
# if 条件判断。如果指定的条件计算为 0 或空字符串,那么该请求不会写入日志。

access_log 指令示例

# 确保nginx源码编译是安装了zlib库
access_log /path/to/log.gz combined gzip flush=5m;

map $status $loggable {
    ~^[23] 0;
    default 1;
}

# if 条件判断,如果有请求的相应码是2xx 或者 3xx ,那么$loggable变量为0 , 这样请求日志不会被打印
access_log  /path/to/access.log main if=$loggable;

每一条日志记录的写入都是先打开文件再写入记录,然后关闭日志文件。如果你的日志文件路径中使用了变量,如 access_log /var/logs/$host/access.log,为提高性能,可以使用 open_log_file_cache 指令设置日志文件描述符的缓存。可以通过 open_log_file_cache off 关闭该缓存。该指令的几个参数选项说明如下:

• max: 设置缓存中最多容纳的文件描述符数量,如果被占满,采用 LRU 算法将描述符
关闭。
• inactive: 设置缓存存活时间,默认是 10s。
• min_uses: 在 inactive 时间段内,日志文件最少使用几次,该日志文件描述符记入缓
存,默认是 1 次。
• valid: 设置多久对日志文件名进行检查,看是否发生变化,默认是 60s。
open_log_file_cache max=100 inactive=15s valid=1m min_users=2;

最后 error_log 是 错误日志配置指令,主要记录客户端访问 Nginx 出错时的日志,它不不支持自定义日志格式。通过检查错误日志,可以快速定位线上问题,所以也是很重要的。关闭错误日志的方式和 access_log 不一样,没有 error_logoff 这样关错误日志的用法,反而会将错误日志打到名为 off 的文件中。常用的关闭方式是:

error_log /dev/null

就像在linux系统中,输出到/dev/null的内容实际上等价于丢弃一样。

Nginx日志切割

Nginx 的日志切割实现的核心是使用 nginx 命令的 reopen 参数实现,该参数的含义是重新开始记录日志文件。人工切的做法就是凌晨将日志备份,然后执行带reopen 参数的命令

[root@centos-13 logs]# ls
access.log  error.log  nginx.pid  rewrite_error.log
[root@centos-13 logs]# mv access.log access1116.log 
[root@centos-13 logs]# mv error.log error1116.log 
[root@centos-13 logs]# ls
access1116.log  error1116.log  nginx.pid  rewrite_error.log
[root@centos-13 logs]# nginx -s reopen
[root@centos-13 logs]# ls
access1116.log  access.log  error1116.log  error.log  nginx.pid  rewrite_error.log

执行后会重新生成 access.log 和 error.log,这就是手工切割的方式。通常我们会用 shell 脚本和定时任务来帮我我们完成自动切割。首先准备如下的shell 脚本,它完成日志的备份以及给 nginx 进程发生 reopen 信号。
Shell脚本(nginx_log_reopen.sh):

nginx_dir=/root/nginx
nginx_log_path=$nginx_dir/logs
nginx_log_bak_path=/var/log/nginx_log_bak

yesterday=$(date -d "yesterday" +%y-%m-%d)

mv  ${nginx_log_path}/access.log  ${nginx_log_bak_path}/access-${yesterday}.log
mv  ${nginx_log_path}/error.log  ${nginx_log_bak_path}/error-${yesterday}.log

# 向nginx  主进程发出USR1信号 ,等同于 -s reopen 选项 , 重新打开日志文件
kill -USR1  ${nginx_dir}/log/nginx.ki

是要将这个脚本加入到定时任务即可。

0 0 * * *  /root/nginx/nginx_log_reopen.sh

案例

Nginx配置如下:

user  root;
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    
    map $status $loggable {
        ~^[34] 0;
        default 1;
    }               
    
    access_log logs/access.log main if=$loggable;
    
    server {
        listen 8000;
        return 200 '8000 , server\n';
    }

    server {
        listen 8001;
        return 300 '8001 , server\n';
    }
    
    server {
        listen 8002;
        return 401 '8002 , server\n';
    }
}

综合了前面涉及的知识,这里只简单测试日志配置中 if 功能。我们设置请求的相应码为 3xx 和 4xx 时,日志不会记录。接下来,启动或者热加载Nginx, 然后分别对应三个端口发送 http 请求并观察 access.log 日志
Curl 端口

[root@centos-13 conf]# curl  127.0.0.1:8000
8000 , server
[root@centos-13 conf]# curl  127.0.0.1:8001
8001 , server
[root@centos-13 conf]# curl  127.0.0.1:8002
8002 , server
[root@centos-13 conf]# curl   http://192.168.232.13:8000 -I
HTTP/1.1 200 OK
Server: nginx/1.22.1
Date: Thu, 17 Nov 2022 09:26:58 GMT
Content-Type: text/plain
Content-Length: 14
Connection: keep-alive

[root@centos-13 conf]# curl   http://192.168.232.13:8001 -I
HTTP/1.1 300 
Server: nginx/1.22.1
Date: Thu, 17 Nov 2022 09:27:02 GMT
Content-Type: text/plain
Content-Length: 14
Connection: keep-alive

[root@centos-13 conf]# curl   http://192.168.232.13:8002 -I
HTTP/1.1 401 Unauthorized
Server: nginx/1.22.1
Date: Thu, 17 Nov 2022 09:27:04 GMT
Content-Type: text/plain
Content-Length: 14
Connection: keep-alive

Access.log日志

[root@centos-13 logs]# pwd
/root/nginx/logs
[root@centos-13 logs]# tail -f access.log
…
192.168.232.13 - - [17/Nov/2022:17:28:46 +0800] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.29.0" "-"
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,923评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,154评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,775评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,960评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,976评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,972评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,893评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,709评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,159评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,400评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,552评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,265评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,876评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,528评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,701评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,552评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,451评论 2 352

推荐阅读更多精彩内容