# Nginx教程 - 5 Nginx日志

# 5.1 日志文件

通过 ./nginx -V 命令可以查看到日志的输出路径,也就是 --http-log-path 指定的位置。

doubi@doubibiji-server:/usr/local/nginx/sbin$ sudo ./nginx -V
nginx version: nginx/1.26.0
built by gcc 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04) 
built with OpenSSL 3.0.2 15 Mar 2022
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --pid-path=/usr/local/nginx/nginx.pid --lock-path=/var/lock/nginx.lock --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --with-http_ssl_module --with-stream --with-http_gzip_static_module --http-client-body-temp-path=/var/temp/nginx/client --http-proxy-temp-path=/var/temp/nginx/proxy --http-fastcgi-temp-path=/var/temp/nginx/fastcgi --http-uwsgi-temp-path=/var/temp/nginx/uwsgi --http-scgi-temp-path=/var/temp/nginx/scgi
1
2
3
4
5
6

在发起请求的时候,会记录每一次请求。例如请求 http://www.abc.com/nginx.jpg 日志的记录如下:

192.168.0.103 - - [01/Jun/2024:13:49:28 +0000] "GET /nginx.jpg HTTP/1.1" 200 24039 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:125.0) Gecko/20100101 Firefox/125.0"
1

上面是默认的日志输出格式,我们还可以在 nginx.conf 中自定义日志的输出格式,在前面介绍 Nginx 配置文件的时候,里面有如下配置:

http {
    # ...其他配置
  
    # log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';  
    # 定义日志格式(包括IP、时间等信息),Nginx内置了一些变量,可以使用 $变量 进行使用
    # 配置文件中,可能是注释掉的,是有默认配置的

    # access_log  /var/log/nginx/access.log  main;  
    # 访问日志文件路径和日志格式,main就是上面日志格式定义的,当用户访问服务器,都会记录日志
  
    # ...其他配置
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

上面 log_format 就是用来定义日志输出格式的,main 就是日志文件的格式名称,后面是日志输出的格式。

access_log 就是定义日志输出,后面 /var/log/nginx/access.log 日志的路径,再后面的 main 表示使用的输出日志的格式,就是前面定义的。

所以可以通过修改 log_format 来修改日志的格式,通过修改access_log 可以修改日志的路径。


定义日志格式使用了很多的内置变量,简单解释一下:

  • $remote_addr: 客户端的 IP 地址;

  • -: 一个连接符号,用于分隔字段;

  • $remote_user: 客户端的用户名,通常通过 HTTP 认证获得。如果没有用户名,则为空;

  • [$time_local]: 本地时间

  • "$request": 请求行,包括方法、URI 和 HTTP 协议版本,如 GET /nginx.jpg HTTP/1.1

  • $status: 响应状态码,如 200404 等。

  • $body_bytes_sent: 发送给客户端的字节数(不包括响应头)。

  • "$http_referer": 引荐地址,即从哪个页面链接到当前请求的页面。如果没有引用页面,则为空。

  • "$http_user_agent": 客户端的 User-Agent 字符串,表示客户端的浏览器、操作系统等信息。

  • "$http_x_forwarded_for": X-Forwarded-For 请求头的值,表示客户端的原始 IP 地址。通常在经过代理或负载均衡器时使用。

# 5.2 server单独指定日志文件

上面的日志是全局配置,所有站点的访问日志都会记录到同一个日志文件中。

所有的站点日志记录到一个文件很混乱,我们也可以为站点单独配置日志文件。

举个例子:

首先在配置文件的 http 节点下,定义日志格式:

log_format  my_log  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';  
1
2
3

然后在 server 节点下,配置日志路径,指定使用上面定义的日志格式:

server {
    listen       80;  
    server_name  www.abc.com;
    access_log   /home/doubi/html_1.log my_log;  # 配置日志目录 和 使用的日志格式

    location / {
        root   /home/doubi/html_1;  # 站点1路径
        index  index.html;
    }
}
1
2
3
4
5
6
7
8
9
10

注意,需要先创建日志目录,并赋予相应的权限。

修改完成,重启 Nginx。

# 5.3 手动切割日志文件

默认 Nginx 的日志都是输出到一个文件中的,是不会按照日期进行切割的,这样会导致文件越来越大,不利于查看。

我们可以编写一个脚本文件,通过命令来进行切割。

例如命令为:cut_nginx_log.sh

#!/bin/bash
# 日志路径
LOG_PATH="/var/log/nginx"

# 生成一个时间的字符串
RECORD_TIME=$(date -d "yesterday" +%Y-%m-%d-%H-%M-%S)

# nginx的PID
PID=/usr/local/nginx/nginx.pid

# 移动文件
mv ${LOG_PATH}/access.log ${LOG_PATH}/access.${RECORD_TIME}.log
mv ${LOG_PATH}/error.log ${LOG_PATH}/error.${RECORD_TIME}.log

# 向Nginx主进程发送信号,用于重新打开日志文件
kill -USR1 `cat $PID`
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

编写好了,赋予文件执行权限。

sudo chmod +x cut_nginx_log.sh
1

然后执行脚本文件:

./cut_nginx_log.sh
1

这样执行一次脚本文件,会将文件重命名,然后生成一个新的日志文件,重新请求 nginx,日志会重新写到 access.log 中。

# 5.4 定时切割日志文件

上面是手动切割,肯定不行,我们要每天定时切割。

这里就需要定时工具 crontabs

# 1 安装crontabs

首先看一下有没有安装 crontabs:

crontab -l
1

如果输出为 no crontab for <username>,则表示当前用户没有定时任务,但 crontab 程序本身是安装的。如果输出显示一系列的 cron 任务,则表示 crontab 已经安装了。

如果系统未安装 crontab,可以使用以下命令安装:

# ubuntu
sudo apt update
sudo apt install cron

# centos
sudo yum install crontabs
1
2
3
4
5
6

# 2 添加定时任务

执行下面的命令来添加定时任务:

# 使用管理员权限运行,给管理员添加定时任务,避免脚本中有脚本没有权限
sudo crontab -e
1
2

第一次运行,可能会选择编辑器, 将如下内容添加到文件中:

# 每分钟执行一次,为了演示
*/1 * * * *   /usr/local/nginx/sbin/cut_nginx_log.sh

# 如果要每天0点0分执行,使用如下:
0 0 * * *   /usr/local/nginx/sbin/cut_nginx_log.sh
1
2
3
4
5

如果选择了cron编辑器,操作方法:

crontab -e 配置完成后,如何把保存并退出?
1.Ctrl+O 写入
2.出现“FIile name to Write...”,输入Enter
3.Ctrl+x 保存输出
提示“crontab:installing new crontab”表示成功。
1
2
3
4
5

保存退出后,可以通过 sudo crontab -l 查看(因为定时任务是针对用户添加的,这里查看也需要sudo)。

关于定时任务表达式,可以去搜索一下 Cron 表达式的写法。

# 3 重启定时任务

重启一下定时任务,使生效。

sudo service crond restart

# 如果找不到服务,可以尝试使用这个
sudo service cron restart
1
2
3
4