日志是排查问题的第一手线索
服务器出了问题,第一反应就是看日志。我处理过的90%的故障,都是通过日志找到原因的。会看日志,解决问题的速度能快十倍。
今天来系统梳理Linux的日志体系和分析方法。
Linux日志体系
日志文件位置
| 日志文件 | 内容 | 查看命令 |
|---|
/var/log/syslog | 系统综合日志 | tail -f /var/log/syslog |
/var/log/auth.log | 认证日志(SSH登录等) | grep "Failed" /var/log/auth.log |
/var/log/kern.log | 内核日志 | tail /var/log/kern.log |
/var/log/nginx/access.log | Nginx访问日志 | tail -f |
/var/log/nginx/error.log | Nginx错误日志 | tail -f |
/var/log/mysql/error.log | MySQL错误日志 | tail |
/var/log/apt/history.log | 软件安装历史 | cat |
1
2
3
4
5
6
7
8
| # 查看有哪些日志文件
$ ls -la /var/log/
total 12456
-rw-r--r-- 1 root root 234567 Feb 12 10:00 syslog
-rw-r----- 1 root adm 56789 Feb 12 10:00 auth.log
-rw-r--r-- 1 root root 12345 Feb 12 09:00 kern.log
drwxr-xr-x 2 root root 4096 Feb 12 10:00 nginx
-rw-r--r-- 1 root root 8901 Feb 12 08:00 dpkg.log
|
journalctl:系统日志管理
systemd的日志系统,功能比直接看文件强大得多。
基本用法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 查看所有日志(从最新的开始)
$ journalctl -r
# 查看最近的日志
$ journalctl -n 50 # 最近50条
# 实时跟踪日志
$ journalctl -f
# 查看特定服务的日志
$ journalctl -u nginx
Feb 12 10:00:01 server nginx[1234]: 2026/02/12 10:00:01 [notice] start worker processes
Feb 12 10:00:01 server nginx[1234]: 2026/02/12 10:00:01 [notice] start worker process 1235
$ journalctl -u mysql -f # 实时跟踪MySQL日志
|
按时间过滤
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # 今天的日志
$ journalctl --since today
# 最近1小时
$ journalctl --since "1 hour ago"
# 指定时间范围
$ journalctl --since "2026-02-12 08:00" --until "2026-02-12 10:00"
# 上次启动以来的日志
$ journalctl -b
# 上上次启动的日志
$ journalctl -b -1
|
按优先级过滤
| 级别 | 数字 | 含义 |
|---|
| emerg | 0 | 系统不可用 |
| alert | 1 | 需要立即处理 |
| crit | 2 | 严重错误 |
| err | 3 | 错误 |
| warning | 4 | 警告 |
| notice | 5 | 普通但重要 |
| info | 6 | 信息 |
| debug | 7 | 调试 |
1
2
3
4
5
6
7
| # 只看错误及以上级别
$ journalctl -p err
Feb 12 03:15:23 server kernel: Out of memory: Killed process 1234 (mysql)
Feb 12 05:30:45 server nginx[5678]: [error] upstream timed out
# 只看严重错误
$ journalctl -p crit
|
日志占用空间管理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # 查看日志占用空间
$ journalctl --disk-usage
Archived and active journals take up 1.5G in the file system.
# 限制日志大小
$ sudo journalctl --vacuum-size=500M
Vacuuming done, freed 1.0G of archived journals.
# 限制日志保留时间
$ sudo journalctl --vacuum-time=7d
# 永久配置
$ sudo vim /etc/systemd/journald.conf
SystemMaxUse=500M
MaxRetentionSec=1week
$ sudo systemctl restart systemd-journald
|
Nginx日志分析
访问日志格式
1
2
3
4
| $ tail -5 /var/log/nginx/access.log
203.0.113.5 - - [12/Feb/2026:10:00:01 +0000] "GET /index.html HTTP/1.1" 200 1234 "-" "Mozilla/5.0"
198.51.100.3 - - [12/Feb/2026:10:00:02 +0000] "POST /api/login HTTP/1.1" 200 567 "https://example.com" "Mozilla/5.0"
192.0.2.100 - - [12/Feb/2026:10:00:03 +0000] "GET /notfound HTTP/1.1" 404 162 "-" "curl/7.88.1"
|
常用分析命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| # 统计HTTP状态码分布
$ awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
15234 200
2345 301
1567 304
890 404
45 500
# 访问量Top 10 IP
$ awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
5234 203.0.113.5
3456 198.51.100.3
1234 192.0.2.100
# 访问量Top 10 URL
$ awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
8901 /
5678 /api/data
2345 /login
890 /favicon.ico
# 统计每小时访问量
$ awk '{print $4}' /var/log/nginx/access.log | cut -d: -f1,2 | sort | uniq -c
120 [12/Feb/2026:08
350 [12/Feb/2026:09
890 [12/Feb/2026:10
# 查找所有500错误
$ grep '" 500 ' /var/log/nginx/access.log
203.0.113.5 - - [12/Feb/2026:10:15:23 +0000] "GET /api/crash HTTP/1.1" 500 234
|
错误日志分析
1
2
3
4
5
6
7
8
9
10
| # 查看最近的错误
$ tail -20 /var/log/nginx/error.log
2026/02/12 10:15:23 [error] 1234#0: *5678 upstream timed out (110: Connection timed out)
2026/02/12 10:20:45 [error] 1234#0: *5679 connect() failed (111: Connection refused)
# 统计错误类型
$ grep -oP '\[error\].*?(?=,)' /var/log/nginx/error.log | sort | uniq -c | sort -rn
45 [error] upstream timed out
23 [error] connect() failed
12 [error] open() failed
|
logrotate:日志轮转
防止日志文件无限增长撑满磁盘。
默认配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| $ cat /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily # 每天轮转
missingok # 日志不存在也不报错
rotate 14 # 保留14个
compress # 压缩旧日志
delaycompress # 延迟压缩
notifempty # 空文件不轮转
create 0640 www-data adm # 新文件的权限
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
endscript
}
|
自定义logrotate配置
1
| $ sudo vim /etc/logrotate.d/myapp
|
1
2
3
4
5
6
7
8
9
10
11
12
| /var/log/myapp/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 0644 deploy deploy
postrotate
systemctl reload myapp > /dev/null 2>&1 || true
endscript
}
|
| 配置项 | 作用 | 常用值 |
|---|
daily/weekly/monthly | 轮转频率 | 按需选择 |
rotate N | 保留份数 | 7-30 |
compress | 压缩旧日志 | 建议开启 |
maxsize 100M | 超过大小就轮转 | 大日志文件 |
minsize 10M | 小于此不轮转 | 避免过度轮转 |
1
2
3
4
5
6
| # 手动触发轮转(测试配置)
$ sudo logrotate -f /etc/logrotate.d/nginx
$ ls -la /var/log/nginx/
-rw-r--r-- 1 www-data adm 0 Feb 12 10:30 access.log
-rw-r--r-- 1 www-data adm 123456 Feb 12 10:30 access.log.1
-rw-r--r-- 1 www-data adm 45678 Feb 11 10:30 access.log.2.gz
|
快速排查流程
服务器出问题时,我的排查流程:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 1. 看系统有没有严重错误
$ journalctl -p err --since "1 hour ago"
# 2. 看对应服务的日志
$ journalctl -u nginx --since "1 hour ago"
# 3. 看应用错误日志
$ tail -50 /var/log/nginx/error.log
# 4. 看系统资源情况(是不是OOM了)
$ journalctl -k | grep -i "out of memory"
$ dmesg | grep -i "oom"
# 5. 看登录日志(是不是被入侵了)
$ grep "Failed password" /var/log/auth.log | tail -20
|
总结
日志分析是运维的核心技能。记住三个关键工具:journalctl看系统日志,tail -f实时跟踪,grep/awk过滤分析。再配合logrotate做好日志轮转,就不用担心日志撑爆磁盘了。
更多文本处理技巧可以看grep、sed、awk实战。服务器监控工具推荐阅读监控工具对比。