nginx按天分割日志

Nginx 本身不支持按天自动切分日志,需要通过外部工具实现。最常用的方法是 logrotate(linux系统自带日志轮转工具),也可以使用 cron 脚本配合 nginx -s reopen 实现。

方法一:使用 logrotate(推荐)

大多数 Linux 发行版安装 Nginx 后会自动创建 /etc/logrotate.d/nginx 配置文件,默认按天轮转。(如果没有需手动创建该文件)

1. 检查现有配置

cat /etc/logrotate.d/nginx

2. 典型配置示例

# *.log日志路径和nginx.pid文件路径根据自己的实际情况配置
/usr/local/nginx/logs/*.log {	
	daily                # 按天轮转
    missingok            # 日志不存在时不报错
    rotate 30            # 保留30天
    dateext          	 # 启用日期后缀
    compress             # 压缩旧日志
    delaycompress        # 延迟压缩(保留最近一个未压缩)
    notifempty           # 空文件不轮转
	# create:指示 logrotate 在轮转(重命名/压缩)旧日志后,创建一个新的空日志文件。
    # 0640 表示:
		# 所有者(nginx 用户):读、写(6 = rw-)
		# 所属组(adm 组):读(4 = r--)
		# 其他人:无任何权限(0 = ---)
		# 即最终权限为 -rw-r-----
	# nginx:新文件的所有者(用户)。通常 Nginx 进程以 nginx 用户运行,这样进程才能写入该日志文件。
	# adm:新文件的所属组。adm 组在 Linux 中常用于系统日志管理,允许属于该组的用户(如管理员)读取日志。
    create 0640 nginx adm
    sharedscripts
    postrotate
        # 重新打开日志文件,注意信号是 USR1 或 reopen
        [ -f /usr/local/nginx/logs/nginx.pid ] && kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`
    endscript
}

postrotate / endscript 含义:定义一个在日志轮转之后执行的脚本块。postrotate开始,endscript结束。脚本可以是任何 Shell 命令。
sharedscripts 含义:指示 logrotate 对所有匹配的日志文件只执行一次 postrotate 中的脚本,而不是为每个日志文件单独执行一次。

copytruncate配置说明见文档

3. 手动测试轮转

# 调试模式 -d​​ 参数表示进行一次调试运行,不会实际修改任何文件,但会显示将要执行的操作。强烈建议调试一下,是否能达到预期效果。
sudo logrotate -d /etc/logrotate.d/nginx

# 强制执行一次轮转(按需)
sudo logrotate -vf /etc/logrotate.d/nginx

4. 查看轮转结果

ls -lh /usr/local/nginx/logs/
# 输出示例(未启用日期后缀):
# access.log          (今天)
# access.log.1        (昨天)
# access.log.2.gz     (前天,已压缩)
# 输出示例(启用日期后缀):
# access.log         	     (今天20260103)
# access.log-20260102        (昨天)
# access.log-20260101.gz     (前天,已压缩)

5. 自动化日志轮转

​​logrotate​​通常由系统的cron任务自动调用。确保​​/etc/cron.daily/logrotate​​文件存在并可执行,这样系统每天都会自动执行日志轮转。
/etc/cron.daily/logrotate

#!/bin/sh

/usr/sbin/logrotate -f /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
    /usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
exit 0

/etc/logrotate.conf

# see "man logrotate" for details
# rotate log files weekly
weekly

# keep 4 weeks worth of backlogs
rotate 4

# create new (empty) log files after rotating old ones
create

# use date as a suffix of the rotated file
dateext

# uncomment this if you want your log files compressed
#compress

# RPM packages drop log rotation information into this directory
include /etc/logrotate.d

# no packages own wtmp and btmp -- we'll rotate them here
/var/log/wtmp {
    monthly
    create 0664 root utmp
        minsize 1M
    rotate 1
}

/var/log/btmp {
    missingok
    monthly
    create 0600 root utmp
    rotate 1
}

# system-specific logs may be also be configured here.

方法二:使用 cron + 脚本手动分割

如果不想使用 logrotate,可以写一个 cron 定时任务。

1. 创建分割脚本 /usr/local/bin/nginx-log-rotate.sh

#!/bin/bash
# Nginx 日志按天分割

LOGS_PATH=/usr/local/nginx/logs
YESTERDAY=$(date -d "yesterday" +%Y%m%d)

# 移动旧日志
mv ${LOGS_PATH}/access.log ${LOGS_PATH}/access_${YESTERDAY}.log
mv ${LOGS_PATH}/error.log ${LOGS_PATH}/error_${YESTERDAY}.log

# 重新打开日志文件
kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`

# 可选:压缩并删除30天前的日志
find ${LOGS_PATH} -name "access_*.log" -mtime +30 -exec gzip {} \;
find ${LOGS_PATH} -name "error_*.log" -mtime +30 -exec gzip {} \;

2. 添加执行权限

chmod +x /usr/local/bin/nginx-log-rotate.sh

3. 添加 cron 任务(每天 00:00 执行)

crontab -e
# 添加一行
0 0 * * * /usr/local/bin/nginx-log-rotate.sh

方法三:使用 Nginx 内置变量(仅适用于访问日志,有一定限制)

Nginx 的 access_log 指令支持变量,可以通过 $time_iso8601 等动态生成日志文件名,实现“按天记录”。但这种方法有性能问题(每次请求都要解析变量并打开新文件),不推荐在高并发下使用。

http {
    # 不建议在高并发下使用
    map $time_iso8601 $logdate {
        ~^(?<ymd>\d{4}-\d{2}-\d{2}) $ymd;
        default 'nodate';
    }
    access_log /usr/local/nginx/logs/access-$logdate.log main;
}

验证日志轮转是否生效

查看当前日志文件

ls -l /usr/local/nginx/logs

查看 logrotate 运行状态

cat /var/lib/logrotate/status | grep nginx

手动触发并观察

sudo logrotate -vf /etc/logrotate.d/nginx
# 观察日志文件变化
watch -n 1 'ls -lh /usr/local/nginx/logs/'

注意事项

  1. 权限问题:确保日志目录和文件权限正确,Nginx 进程用户(通常是 www-datanginx)有写权限。
  2. 信号处理:重新打开日志的正确信号是 USR1nginx -s reopen 也能达到同样效果。在 logrotate 脚本中推荐使用 kill -USR1
  3. 日志格式:如果自定义了日志格式,access_log 指令中需要指定格式名称。
  4. 容器环境:如果运行在 Docker 中,建议将日志输出到 stdout/stderr,由容器运行时或日志驱动处理,而不是在容器内分割。

总结

  • 最佳实践:使用系统自带的 logrotate,配置简单且稳定。
  • 备选方案:cron 脚本。
  • 不推荐:Nginx 变量动态文件名(高并发下性能差)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值