# Nginx 日志分割方案

Nginx 默认不会自动分割日志文件，随着时间推移日志文件会变得非常大，影响系统性能和管理。以下是几种常用的 Nginx 日志分割方法：

## 1. 使用 logrotate (推荐)

logrotate 是 Linux 系统自带的日志管理工具，非常适合用于 Nginx 日志分割。

### 配置步骤

1. 创建 logrotate 配置文件 (通常放在 `/etc/logrotate.d/nginx`)

```bash
sudo nano /etc/logrotate.d/nginx
```

2. 添加以下内容：

```
/var/log/nginx/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        if [ -f /var/run/nginx.pid ]; then
            kill -USR1 `cat /var/run/nginx.pid`
        fi
    endscript
}
```

### 参数说明

- `daily`: 每天轮转
- `missingok`: 如果日志文件不存在也不报错
- `rotate 14`: 保留14个旧日志文件
- `compress`: 使用 gzip 压缩旧日志
- `delaycompress`: 延迟压缩前一个日志文件
- `notifempty`: 如果日志为空则不轮转
- `create 0640 www-data adm`: 创建新日志文件的权限和所有者
- `sharedscripts`: 所有日志处理完后才运行 postrotate 脚本
- `postrotate`: 通知 Nginx 重新打开日志文件

3. 测试配置是否正确

```bash
sudo logrotate -d /etc/logrotate.d/nginx
```

4. 手动运行 logrotate

```bash
sudo logrotate -f /etc/logrotate.d/nginx
```

## 2. 使用 cron 脚本手动分割

1. 创建日志分割脚本 `/usr/local/bin/nginx_logrotate.sh`:

```bash
#!/bin/bash
# Nginx 日志目录
LOGS_PATH=/var/log/nginx
# 获取昨天日期
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
# 向 Nginx 主进程发送 USR1 信号，重新打开日志文件
kill -USR1 $(cat /var/run/nginx.pid)
```

2. 给脚本执行权限

```bash
chmod +x /usr/local/bin/nginx_logrotate.sh
```

3. 设置 cron 任务每天执行

```bash
crontab -e
```

添加以下内容（每天午夜执行）：

```
0 0 * * * /usr/local/bin/nginx_logrotate.sh
```

## 3. 使用系统自带的时间戳日志 (Nginx 1.19.6+)

Nginx 1.19.6 及以上版本支持在日志文件名中使用变量：

```nginx
http {
    log_format custom '$remote_addr - $remote_user [$time_local] '
                      '"$request" $status $body_bytes_sent '
                      '"$http_referer" "$http_user_agent"';
    
    access_log /var/log/nginx/access-${year}${month}${day}.log custom;
}
```

然后使用 `map` 指令定义时间变量：

```nginx
map $time_iso8601 $year {
    default '0000';
    '~^(?<yyyy>\d{4})-' $yyyy;
}

map $time_iso8601 $month {
    default '00';
    '~^\d{4}-(?<mm>\d{2})-' $mm;
}

map $time_iso8601 $day {
    default '00';
    '~^\d{4}-\d{2}-(?<dd>\d{2})' $dd;
}
```

## 日志分割后的管理

1. **删除旧日志**：定期清理过期的日志文件
2. **日志分析**：使用工具如 GoAccess、AWStats 分析分割后的日志
3. **日志备份**：重要的日志文件可以备份到远程存储

## 注意事项

1. 确保 Nginx 进程有权限写入新的日志文件
2. 分割日志时确保磁盘空间充足
3. 生产环境建议使用 logrotate 方案，它更可靠且功能完善
4. 对于高流量网站，可以考虑按小时分割日志

以上方法可以根据实际需求选择或组合使用，logrotate 通常是大多数 Linux 发行版的首选方案。