nginx

关注公众号 jb51net

关闭
首页 > 网站技巧 > 服务器 > nginx > Nginx日志文件位置与查看

Nginx日志文件的位置与基础查看指南

作者:知远漫谈

你是否曾在服务器上遇到网站打不开、502 Bad Gateway、404 Not Found这类令人抓狂的错误?
你是否曾对着空白的终端发呆,不知道从哪里下手排查问题?别慌——你不是一个人,本文将从零开始,彻底搞懂Nginx日志的位置、结构、查看方式、分析技巧

引言

你是否曾在服务器上遇到“网站打不开”、“502 Bad Gateway”、“404 Not Found”这类令人抓狂的错误?
你是否曾对着空白的终端发呆,不知道从哪里下手排查问题?
你是否在同事说“看下Nginx日志”时,心里默默问:“日志?在哪?怎么打开?看啥?”

别慌——你不是一个人。
每一个Nginx老司机,都曾是今天的小白。
而今天,你将从零开始,彻底搞懂Nginx日志的位置、结构、查看方式、分析技巧,甚至还能用Java写个小工具自动分析日志!

无论你是刚入行的运维新人、前端开发者、后端Java工程师,还是想自己搭个博客的爱好者,这篇文章都会成为你日志排查路上的“导航仪”。
我们不讲高深理论,只讲你能马上用上的实战技巧
准备好你的终端、你的IDE、你的咖啡,我们开始吧!

什么是Nginx?为什么日志这么重要?

Nginx(发音为“engine-x”)是一个高性能的HTTP和反向代理服务器,也是当今互联网最流行的Web服务器之一。
它被广泛用于:

而日志,就是Nginx的“黑匣子”——它默默记录了每一个请求的来龙去脉。

想象一下:
你的网站突然访问量暴增,用户投诉“页面加载慢”。
你登录服务器,打开Nginx日志,发现某几个IP在高频请求一个不存在的API接口,疑似爬虫或攻击。
你立刻用防火墙封禁这些IP,问题解决。
——这就是日志的力量。

日志 = 问题的线索,安全的哨兵,性能的镜子

没有日志,你就像在黑暗中开车——没有导航,没有路灯,只有撞墙的可能。

Nginx日志文件默认位置在哪?

Nginx的日志文件位置,不是固定的,它取决于你的系统、安装方式和配置文件。

但!有绝大多数情况下的标准路径,我们先记住这些:

Linux系统(Ubuntu / CentOS / Debian)

日志类型默认路径
访问日志(access log)/var/log/nginx/access.log
错误日志(error log)/var/log/nginx/error.log

💡 为什么是这两个?因为Nginx在安装时,会默认使用/var/log/nginx/作为日志目录,这是Linux FHS(文件系统层次结构标准)推荐的路径。

macOS(通过Homebrew安装)

/usr/local/var/log/nginx/access.log
/usr/local/var/log/nginx/error.log

Docker容器中的Nginx

如果你是用Docker部署的Nginx,日志默认会输出到标准输出(stdout)和标准错误(stderr),也就是说:

docker logs your-nginx-container

就可以看到日志内容。
如果你想持久化日志,需要挂载宿主机目录:

docker run -d \
  -v /host/logs/nginx:/var/log/nginx \
  --name my-nginx \
  nginx

这样日志就会保存在你宿主机的 /host/logs/nginx/ 目录下。

自定义配置下的日志位置

Nginx的配置文件通常是:

/etc/nginx/nginx.conf

打开它,你会看到类似这样的配置:

http {
    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 /var/log/nginx/access.log main;
    error_log /var/log/nginx/error.log warn;
}

所以,最准确的方法是:直接查看你的nginx.conf文件!

你可以用以下命令快速定位:

# 查看Nginx主配置文件路径
nginx -t

# 输出类似:
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful

# 然后查看配置
cat /etc/nginx/nginx.conf | grep -E "access_log|error_log"

小贴士:如果你不确定Nginx配置文件在哪,可以用 which nginx 找到Nginx可执行文件,然后运行 nginx -V 查看编译参数,里面会包含 --prefix=,这就是Nginx的根目录。

Nginx日志文件详解:访问日志 vs 错误日志

Nginx有两个核心日志文件,它们的用途完全不同。

访问日志(access.log):谁在访问?访问了什么?

这是你每天看得最多的日志。
它记录了每一个HTTP请求的详细信息

默认格式示例:

192.168.1.100 - - [25/Apr/2024:10:30:22 +0800] "GET /index.html HTTP/1.1" 200 1234 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" "-"

我们来逐项拆解:

字段含义示例
$remote_addr客户端IP地址192.168.1.100
$remote_user认证用户(通常为--
$time_local请求时间(本地时区)[25/Apr/2024:10:30:22 +0800]
$request请求方法 + URI + 协议"GET /index.html HTTP/1.1"
$statusHTTP响应状态码200
$body_bytes_sent发送给客户端的字节数(不含响应头)1234
$http_referer来源页面(Referer)"-"(无来源)
$http_user_agent客户端浏览器/设备信息"Mozilla/5.0 ... Chrome/123.0..."
$http_x_forwarded_for代理链中的原始IP(如果有)"-"

你知道吗?如果你的网站前面有CDN(如Cloudflare)或负载均衡器,$remote_addr 可能是CDN的IP,而不是真实用户IP。这时就要依赖 $http_x_forwarded_for

自定义日志格式(进阶)

你可以在 nginx.conf 中自定义日志格式,比如增加响应时间:

log_format detailed '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
                    '$request_time $upstream_response_time';

access_log /var/log/nginx/access.log detailed;

现在日志会多出两个字段:

这两个字段对性能分析至关重要!后面我们会用Java程序分析它们。

访问日志能告诉你什么?

问题日志线索
用户访问慢$request_time > 2s
404 页面多$status = 404,且请求路径是无效API
恶意扫描大量请求 /wp-admin, /phpmyadmin, /robots.txt
高频爬虫同一IP在1秒内请求50次
网站被攻击大量 POST /login 请求,状态码为401/403

错误日志(error.log):Nginx自己在抱怨什么?

访问日志记录的是“用户干了啥”,而错误日志记录的是“Nginx自己遇到了啥问题”。

默认错误日志示例:

2024/04/25 10:31:15 [error] 1234#1234: *5678 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.1.100, server: example.com, request: "GET /api/user HTTP/1.1", upstream: "http://127.0.0.1:8080/api/user", host: "example.com"

我们来解析:

字段含义
2024/04/25 10:31:15时间戳
[error]日志级别(还有 warn, info, notice
1234#1234进程ID和线程ID
*5678连接ID
connect() failed (111: Connection refused)错误原因
while connecting to upstream正在连接后端服务
client: 192.168.1.100请求客户端
server: example.com请求的域名
request: "GET /api/user HTTP/1.1"请求内容
upstream: "http://127.0.0.1:8080/api/user"后端地址

常见错误类型

错误类型原因解决方案
Connection refused后端服务(如Java应用)没启动或端口不对systemctl status java-app,检查端口监听
No such file or directory请求的静态文件不存在检查 root 路径是否正确,文件权限
upstream timed out后端响应太慢(> proxy_read_timeout)调大 proxy_read_timeout,优化Java服务性能
Permission deniedNginx无权读取文件或连接socketchown -R www-data:www-data /var/www/html
SSL_do_handshake() failedSSL证书配置错误检查 .crt.key 文件路径、权限、是否过期

注意:error.log 默认级别是 error,意味着只记录错误。
如果你想看到更详细的调试信息,可以临时改成 debug

error_log /var/log/nginx/error.log debug;

但!不要在生产环境长期开启debug,它会产生海量日志,拖垮磁盘和性能!

如何查看Nginx日志?终端命令实战

光知道日志在哪还不够,你得会“看”。

基础命令:cat,less,tail

1.cat:一次性全部打印(适合小文件)

cat /var/log/nginx/access.log

不推荐用于大文件!会刷屏,卡死终端。

2.less:分页查看(推荐!)

less /var/log/nginx/access.log

3.tail:实时追踪最新日志(最常用!)

tail -f /var/log/nginx/access.log

-f = follow,实时刷新。
你打开这个命令,然后在浏览器刷新页面,终端立刻会看到新日志!

4.tail -n 50:只看最后50行

tail -n 50 /var/log/nginx/error.log

5.grep:过滤关键词(神器!)

# 查看所有404错误
grep " 404 " /var/log/nginx/access.log

# 查看所有502错误
grep " 502 " /var/log/nginx/error.log

# 查看某个IP的所有请求
grep "192.168.1.100" /var/log/nginx/access.log

# 查看请求时间超过2秒的请求(需要配合awk)
awk '$10 > 2 {print}' /var/log/nginx/access.log

为什么是 grep " 404 "?因为 $status 前后都有空格,避免匹配到 14044041 等错误数字。

6.awk:按字段提取(数据分析利器)

# 提取所有状态码和访问次数
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -nr

# 输出示例:
#   1234 200
#    234 404
#     89 500
# 提取前10个最频繁访问的URL
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10
# 提取访问时间最长的前5个请求(假设你用了detailed格式,第10列是$request_time)
awk '{print $10, $7}' /var/log/nginx/access.log | sort -nr | head -5

7.journalctl(systemd系统专用)

如果你的Nginx是通过systemd管理的(大多数现代Linux都是):

# 查看Nginx服务日志(包含access和error)
journalctl -u nginx

# 实时追踪
journalctl -u nginx -f

# 只看最近1小时
journalctl -u nginx --since "1 hour ago"

journalctl 是现代Linux的统一日志系统,比直接读文件更强大!

用Java写一个Nginx日志分析小工具(实战!)

现在,我们来点硬核的——用Java写一个程序,自动分析Nginx访问日志,统计Top 10最慢请求、404统计、IP访问频率

准备工作

你需要:

示例日志文件(access.log)

我们创建一个简单的测试日志文件:

192.168.1.100 - - [25/Apr/2024:10:30:22 +0800] "GET /api/v1/user HTTP/1.1" 200 1234 "-" "Mozilla/5.0" 0.045 0.042
192.168.1.101 - - [25/Apr/2024:10:30:23 +0800] "GET /api/v1/product HTTP/1.1" 404 567 "-" "curl/7.68.0" 0.002 0.001
192.168.1.100 - - [25/Apr/2024:10:30:24 +0800] "GET /api/v1/user HTTP/1.1" 200 1234 "-" "Mozilla/5.0" 0.089 0.085
192.168.1.102 - - [25/Apr/2024:10:30:25 +0800] "GET /admin HTTP/1.1" 404 567 "-" "Mozilla/5.0" 0.001 0.000
192.168.1.103 - - [25/Apr/2024:10:30:26 +0800] "GET /api/v1/order HTTP/1.1" 500 1000 "-" "PostmanRuntime/7.30.0" 2.100 2.050
192.168.1.100 - - [25/Apr/2024:10:30:27 +0800] "GET /api/v1/user HTTP/1.1" 200 1234 "-" "Mozilla/5.0" 0.033 0.030
192.168.1.104 - - [25/Apr/2024:10:30:28 +0800] "GET /favicon.ico HTTP/1.1" 404 567 "-" "Mozilla/5.0" 0.001 0.000
192.168.1.105 - - [25/Apr/2024:10:30:29 +0800] "GET /api/v1/product HTTP/1.1" 404 567 "-" "curl/7.68.0" 0.002 0.001
192.168.1.106 - - [25/Apr/2024:10:30:30 +0800] "POST /login HTTP/1.1" 401 120 "-" "BurpSuite" 0.005 0.004
192.168.1.107 - - [25/Apr/2024:10:30:31 +0800] "GET /api/v1/user HTTP/1.1" 200 1234 "-" "Mozilla/5.0" 0.022 0.020

注意:我们假设日志格式是 detailed 格式,最后两列是 $request_time$upstream_response_time

Java代码:NginxLogAnalyzer

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class NginxLogAnalyzer {
    public static void main(String[] args) {
        String logFilePath = "/var/log/nginx/access.log"; // 替换为你的日志路径
        System.out.println("🚀 Nginx日志分析工具启动中... 🚀\n");
        try {
            List<LogEntry> logs = parseLogEntries(logFilePath);
            if (logs.isEmpty()) {
                System.out.println("⚠️ 未找到有效日志条目,请检查文件路径或格式。\n");
                return;
            }
            System.out.println("📊 分析结果如下:\n");
            // 1. 统计HTTP状态码分布
            analyzeStatusCodes(logs);
            // 2. 找出最慢的10个请求
            analyzeSlowestRequests(logs);
            // 3. 统计Top 10 IP访问频率
            analyzeTopIPs(logs);
            // 4. 统计404错误最多的URL
            analyzeTop404Urls(logs);
            // 5. 检测异常行为:同一IP在1秒内请求>5次
            detectSuspiciousActivity(logs);
        } catch (IOException e) {
            System.err.println("❌ 读取日志文件失败: " + e.getMessage());
        }
    }
    // 解析每一行日志
    static List<LogEntry> parseLogEntries(String filePath) throws IOException {
        List<LogEntry> entries = new ArrayList<>();
        try (Stream<String> lines = Files.lines(Paths.get(filePath))) {
            lines.filter(line -> !line.trim().isEmpty())
                 .forEach(line -> {
                     try {
                         LogEntry entry = parseLogLine(line);
                         if (entry != null) entries.add(entry);
                     } catch (Exception e) {
                         // 忽略格式错误的行
                         System.err.println("⚠️ 解析失败行: " + line);
                     }
                 });
        }
        return entries;
    }
    // 解析单行日志(按空格分割,注意URL可能含空格,所以不能简单split)
    static LogEntry parseLogLine(String line) {
        // 我们假设格式是:IP - - [时间] "请求" 状态 字节数 "Referer" "UA" 请求耗时 上游耗时
        // 用正则更安全,但为简化,我们按空格拆分,然后合并请求字段
        String[] parts = line.split(" ", 10); // 最多切10份
        if (parts.length < 10) return null;
        String clientIp = parts[0];
        String requestTimeStr = parts[3].substring(1); // 去掉 [
        String request = parts[5] + " " + parts[6] + " " + parts[7]; // GET /api/user HTTP/1.1
        int status = Integer.parseInt(parts[8]);
        long bodyBytes = Long.parseLong(parts[9]);
        double requestTime = Double.parseDouble(parts[10]);
        double upstreamTime = parts.length > 11 ? Double.parseDouble(parts[11]) : 0.0;
        // 提取时间
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MMM/yyyy:HH:mm:ss Z");
        LocalDateTime time = LocalDateTime.parse(requestTimeStr, formatter);
        return new LogEntry(
            clientIp,
            time,
            request,
            status,
            bodyBytes,
            requestTime,
            upstreamTime
        );
    }
    // 统计状态码分布
    static void analyzeStatusCodes(List<LogEntry> logs) {
        Map<Integer, Long> statusCount = logs.stream()
            .collect(Collectors.groupingBy(LogEntry::getStatus, Collectors.counting()));
        System.out.println("🔢 HTTP状态码统计:");
        statusCount.entrySet().stream()
            .sorted(Map.Entry.<Integer, Long>comparingByValue().reversed())
            .forEach(e -> System.out.printf("    %d: %d 次%n", e.getKey(), e.getValue()));
        System.out.println();
    }
    // 找出最慢的10个请求
    static void analyzeSlowestRequests(List<LogEntry> logs) {
        System.out.println("🐢 最慢的10个请求(按$request_time排序):");
        logs.stream()
            .sorted(Comparator.comparingDouble(LogEntry::getRequestTime).reversed())
            .limit(10)
            .forEach(entry -> System.out.printf(
                "    %.3fs | %d %s | IP: %s%n",
                entry.getRequestTime(),
                entry.getStatus(),
                entry.getRequest(),
                entry.getClientIp()
            ));
        System.out.println();
    }
    // 统计Top 10 IP访问频率
    static void analyzeTopIPs(List<LogEntry> logs) {
        System.out.println("📍 Top 10 访问IP:");
        logs.stream()
            .collect(Collectors.groupingBy(LogEntry::getClientIp, Collectors.counting()))
            .entrySet().stream()
            .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
            .limit(10)
            .forEach(e -> System.out.printf("    %s: %d 次%n", e.getKey(), e.getValue()));
        System.out.println();
    }
    // 统计404错误最多的URL
    static void analyzeTop404Urls(List<LogEntry> logs) {
        System.out.println("🔍 404错误最多的URL(前5):");
        logs.stream()
            .filter(entry -> entry.getStatus() == 404)
            .collect(Collectors.groupingBy(LogEntry::getRequest, Collectors.counting()))
            .entrySet().stream()
            .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
            .limit(5)
            .forEach(e -> System.out.printf("    %s: %d 次%n", e.getKey(), e.getValue()));
        System.out.println();
    }
    // 检测可疑行为:同一IP在1秒内请求>5次
    static void detectSuspiciousActivity(List<LogEntry> logs) {
        System.out.println("🚨 可疑行为检测(同一IP在1秒内>5次请求):");
        Map<String, List<LogEntry>> ipGroups = logs.stream()
            .collect(Collectors.groupingBy(LogEntry::getClientIp));
        ipGroups.entrySet().stream()
            .filter(entry -> entry.getValue().size() > 5)
            .forEach(entry -> {
                String ip = entry.getKey();
                List<LogEntry> requests = entry.getValue();
                requests.sort(Comparator.comparing(LogEntry::getTime));
                // 检查是否存在连续5个请求在1秒内
                for (int i = 0; i <= requests.size() - 5; i++) {
                    LocalDateTime start = requests.get(i).getTime();
                    LocalDateTime end = requests.get(i + 4).getTime();
                    long diffSeconds = java.time.Duration.between(start, end).getSeconds();
                    if (diffSeconds <= 1) {
                        System.out.printf("    ⚠️ IP: %s 在 %s 到 %s 间发起 %d 次请求(%d秒内)%n",
                            ip, start, end, 5, diffSeconds);
                        break;
                    }
                }
            });
        System.out.println();
    }
    // 日志条目模型
    static class LogEntry {
        private final String clientIp;
        private final LocalDateTime time;
        private final String request;
        private final int status;
        private final long bodyBytes;
        private final double requestTime;
        private final double upstreamTime;
        public LogEntry(String clientIp, LocalDateTime time, String request, int status,
                        long bodyBytes, double requestTime, double upstreamTime) {
            this.clientIp = clientIp;
            this.time = time;
            this.request = request;
            this.status = status;
            this.bodyBytes = bodyBytes;
            this.requestTime = requestTime;
            this.upstreamTime = upstreamTime;
        }
        // Getters
        public String getClientIp() { return clientIp; }
        public LocalDateTime getTime() { return time; }
        public String getRequest() { return request; }
        public int getStatus() { return status; }
        public long getBodyBytes() { return bodyBytes; }
        public double getRequestTime() { return requestTime; }
        public double getUpstreamTime() { return upstreamTime; }
    }
}

运行效果示例

假设你运行上面的程序,输入我们上面的测试日志,输出如下:

🚀 Nginx日志分析工具启动中... 🚀

📊 分析结果如下:

🔢 HTTP状态码统计:
    200: 5 次
    404: 4 次
    401: 1 次
    500: 1 次

🐢 最慢的10个请求(按$request_time排序):
    2.100s | 500 GET /api/v1/order HTTP/1.1 | IP: 192.168.1.103
    0.089s | 200 GET /api/v1/user HTTP/1.1 | IP: 192.168.1.100
    0.045s | 200 GET /api/v1/user HTTP/1.1 | IP: 192.168.1.100
    0.033s | 200 GET /api/v1/user HTTP/1.1 | IP: 192.168.1.100
    0.022s | 200 GET /api/v1/user HTTP/1.1 | IP: 192.168.1.107
    0.005s | 401 POST /login HTTP/1.1 | IP: 192.168.1.106
    0.002s | 404 GET /api/v1/product HTTP/1.1 | IP: 192.168.1.101
    0.002s | 404 GET /api/v1/product HTTP/1.1 | IP: 192.168.1.105
    0.001s | 404 GET /admin HTTP/1.1 | IP: 192.168.1.102
    0.001s | 404 GET /favicon.ico HTTP/1.1 | IP: 192.168.1.104

📍 Top 10 访问IP:
    192.168.1.100: 4 次
    192.168.1.101: 1 次
    192.168.1.102: 1 次
    192.168.1.103: 1 次
    192.168.1.104: 1 次
    192.168.1.105: 1 次
    192.168.1.106: 1 次
    192.168.1.107: 1 次

🔍 404错误最多的URL(前5):
    GET /api/v1/product HTTP/1.1: 2 次
    GET /admin HTTP/1.1: 1 次
    GET /favicon.ico HTTP/1.1: 1 次

🚨 可疑行为检测(同一IP在1秒内>5次请求):
    (无输出,说明没有异常)

你看到了吗?

用Mermaid画日志分析流程图(可视化你的思维)

我们来用Mermaid画一个Nginx日志分析流程图,帮你理清思路:

这张图不是装饰品,它是你排查问题的思维导图
每次遇到问题,先对照这张图,一步步走下来,不会漏掉关键点。

高频问题排查实战:5个真实场景

场景1:用户说“网站打不开”,但Nginx进程是running的

现象:浏览器显示 502 Bad Gateway

排查步骤

  1. 查看 error.log
tail -f /var/log/nginx/error.log
  1. 看到:
connect() failed (111: Connection refused) while connecting to upstream
  1. 说明:Nginx想转发请求给后端(如Java),但后端没在监听。
  2. 解决:
# 检查Java应用是否启动
ps aux | grep java

# 检查端口是否监听
netstat -tlnp | grep 8080

# 或者用 ss(推荐)
ss -tlnp | grep 8080

# 如果没监听 → 启动Java应用
nohup java -jar your-app.jar > app.log 2>&1 &

你也可以用 curl http://localhost:8080/health 测试后端是否正常。

场景2:大量404错误,用户访问了不存在的页面

现象access.log 中出现大量 GET /wp-adminGET /robots.txtGET /api/v1/user/123456(但API不存在)

排查

grep " 404 " /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -nr | head -20

发现

  1200 /wp-admin
   800 /phpmyadmin
   500 /api/v1/user/123456

解决

安全建议:不要在404页面暴露系统结构。返回统一的“页面不存在”即可。

场景3:页面加载慢,但后端Java服务响应很快

现象access.log$request_time = 3s,但 $upstream_response_time = 0.01s

分析

可能原因

解决

# 启用缓冲
proxy_buffering on;
proxy_buffer_size 128k;
proxy_buffers 4 256k;

# 增加超时
proxy_read_timeout 60s;
proxy_connect_timeout 60s;

# 缓存静态资源
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

场景4:同一个IP在1秒内请求100次

现象access.log 中某IP连续请求 /api/login,状态码全是401

分析

解决

  1. fail2ban 自动封禁IP:
sudo apt install fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

编辑 /etc/fail2ban/jail.local

[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 3
bantime = 3600

重启:

sudo systemctl restart fail2ban
  1. 或者用Nginx内置限流:
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=1r/s;

server {
    location /api/login {
        limit_req zone=login_limit burst=5 nodelay;
        proxy_pass http://backend;
    }
}

场景5:日志文件太大,磁盘快满了!

现象df -h 显示 /var 使用率 98%

解决

  1. 清理旧日志
# 查看日志大小
ls -lh /var/log/nginx/

# 清空日志(保留文件,清空内容)
> /var/log/nginx/access.log

# 或者压缩归档
gzip /var/log/nginx/access.log
mv /var/log/nginx/access.log.gz /var/log/nginx/access.log.20240425.gz
  1. 配置日志轮转(logrotate)

编辑 /etc/logrotate.d/nginx

/var/log/nginx/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
    endscript
}

这样,Nginx每天自动轮转日志,保留14天,自动压缩,不会撑爆磁盘。

生产环境必须配置logrotate!

自动化:用Shell脚本每天发日志摘要邮件

你不想每天登录服务器看日志?我们可以写个脚本,每天早上8点自动发一封邮件给你!

#!/bin/bash
# /usr/local/bin/nginx-daily-report.sh

LOG_FILE="/var/log/nginx/access.log"
REPORT_FILE="/tmp/nginx-report-$(date +%Y%m%d).txt"

echo "📊 Nginx日志日报 - $(date)" > $REPORT_FILE
echo "=========================================" >> $REPORT_FILE

# 统计总请求数
TOTAL=$(wc -l < $LOG_FILE)
echo "✅ 总请求数: $TOTAL" >> $REPORT_FILE

# 统计404
ERROR_404=$(grep " 404 " $LOG_FILE | wc -l)
echo "❌ 404错误: $ERROR_404" >> $REPORT_FILE

# 最慢的3个请求
echo -e "\n🐢 最慢的3个请求:" >> $REPORT_FILE
awk '{print $10, $7}' $LOG_FILE | sort -nr | head -3 >> $REPORT_FILE

# 发送邮件(需配置sendmail或postfix)
mail -s "Nginx日志日报 $(date +%Y-%m-%d)" your-email@example.com < $REPORT_FILE

# 清理
rm $REPORT_FILE

然后加到crontab:

crontab -e

添加:

0 8 * * * /usr/local/bin/nginx-daily-report.sh

每天早上8点,你的邮箱就会收到一份Nginx日志摘要!

企业级做法:用ELK(Elasticsearch + Logstash + Kibana)或Grafana Loki做可视化日志平台。

# Ubuntu安装GoAccess
sudo apt install goaccess

# 实时分析Nginx日志
goaccess /var/log/nginx/access.log --log-format=COMBINED -a

你会看到一个彩色终端仪表盘,实时显示:访问量、来源、浏览器、操作系统、地理分布!

总结:小白到高手的Nginx日志成长路径

阶段你该掌握的技能
🐣 小白知道日志在哪,会用 tail -f
🐱 初级会用 grepawksort 做简单统计
🐶 中级会写Java/Python脚本自动化分析,识别404、慢请求
🐘 高级会配置logrotate、fail2ban、限流、自定义日志格式
🦸‍♂️ 大神会搭建ELK、写Prometheus监控、做日志告警、优化Nginx性能

最后的话:日志是你的战友,不是敌人

很多开发者讨厌看日志,觉得它“枯燥”、“乱糟糟”、“看不懂”。

但真正厉害的工程师,把日志当小说读

每一个 404,都是一个用户找不到入口的叹息;
每一个 502,都是后端服务在喘息;
每一个 200,都是系统在默默为你服务。

你读得越多,就越懂你的系统。

不要等到线上崩溃才去看日志。
每天花5分钟,看看Nginx日志,你会成为团队里最靠谱的那个人。

附录:常用Nginx日志变量速查表

变量名含义示例
$remote_addr客户端IP192.168.1.100
$time_local本地时间[25/Apr/2024:10:30:22 +0800]
$request请求行GET /api/user HTTP/1.1
$statusHTTP状态码200
$body_bytes_sent响应体大小(字节)1234
$http_referer来源页面https://google.com
$http_user_agent用户代理Mozilla/5.0 Chrome/123
$request_timeNginx处理耗时0.045
$upstream_response_time后端响应耗时0.042
$upstream_status后端返回状态码200
$http_x_forwarded_for代理链原始IP192.168.1.1, 10.0.0.1

结语:你,已经不是那个怕看日志的小白了

今天,你学会了:

你已经超越了80%的程序员。

现在,打开你的终端,运行:

tail -f /var/log/nginx/access.log

然后,静静地看着那些字符流动——
那是你系统的心跳,
是你服务的生命线。

你,现在是一个能读懂日志的人了。

记住:真正的技术,不是写多少行代码,而是能看懂系统在说什么。

以上就是Nginx日志文件的位置与基础查看指南的详细内容,更多关于Nginx日志文件位置与查看的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文