Linux日志文件
一、主要日志文件位置及含义
系统核心日志
二、基础查看命令详解
1. 实时监控类命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| # 命令:tail -f /var/log/messages
# 含义:
# - tail:显示文件末尾内容
# - -f (follow):实时跟踪文件新增内容,不会自动退出
# 应用场景:重现问题时实时观察日志输出
# 退出方式:按 Ctrl+C 终止
# 示例:监控最后100行并持续更新
tail -100f /var/log/syslog
# -100:先显示最后100行,然后进入跟踪模式
# 比直接tail -f更有用,可以看到问题发生前的上下文
# 同时监控多个日志文件
tail -f /var/log/messages /var/log/secure
# 输出格式:[文件路径] 实际日志内容
# 这样可以关联分析多个服务的交互问题
|
输出示例解读:
1
2
| Nov 10 14:25:01 server sshd[12345]: Failed password for root from 192.168.1.100 port 3321 ssh2
# 时间戳 主机名 进程名[PID]: 具体消息内容
|
2. 分页浏览工具
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| # 命令:less /var/log/messages
# 核心优势:
# 1. 加载大文件速度快(不像vim会一次性加载全部)
# 2. 支持前后翻页,适合深入分析
# 3. 搜索功能强大,不会阻塞
# less中的关键操作:
# /keyword 向后搜索关键词(输入后按回车)
# ?keyword 向前搜索关键词
# n 跳转到下一个匹配项 (next)
# N 跳转到上一个匹配项
# G 跳到文件末尾 (goto end)
# g 跳到文件开头
# 空格键 向下翻页
# b 向上翻页 (back)
# q 退出 (quit)
# 实用技巧:less +F /var/log/messages
# +F参数:启动时直接进入跟踪模式(类似tail -f)
# 按Ctrl+C退出跟踪模式,转为普通浏览模式
|
3. 精确时间范围查看
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # 命令:grep "Nov 10" /var/log/messages
# 含义:筛选包含"Nov 10"字符串的行(11月10日的日志)
# 局限性:会匹配到所有含该字符串的内容,可能不够精确
# 更精确的时间匹配(使用正则表达式)
grep "^Nov 10 14:2[0-9]" /var/log/messages
# ^:行首锚定,确保从时间戳开始匹配
# 14:2[0-9]:匹配14:20-14:29的时间段
# 使用awk提取特定时间范围
awk '$2=="10" && $3>="14:00:00" && $3<="14:30:00"' /var/log/messages
# $2:第二列(日期)
# $3:第三列(时间)
# 逻辑:日期是10号且时间在14:00-14:30之间
|
三、进阶分析技巧深度解析
1. grep搜索实战详解
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
31
32
| # 基础错误查找(不区分大小写)
grep -i "error" /var/log/messages
# -i (ignore case):忽略大小写,匹配Error、ERROR、error等
# 为什么用:避免遗漏不同格式的错误信息
# 同时查找多个关键词(使用正则表达式)
grep -i "error\|fail\|critical\|denied" /var/log/messages
# \|:正则表达式的"或"操作符
# 为什么用:不同类型的错误可能使用不同词汇描述
# 显示匹配行的上下文(最关键的技巧)
grep -C 5 -i "fatal" /var/log/messages
# -C 5 (Context):显示匹配行前后各5行
# 为什么用:单个错误行往往信息不足,需要上下文定位根本原因
# -A 5 (After):只显示后5行
# -B 5 (Before):只显示前5行
# 排除干扰信息(反向匹配)
grep "error" /var/log/messages | grep -v "debug"
# |:管道符,将前一个命令的输出作为后一个命令的输入
# grep -v:反向匹配,排除包含指定关键词的行
# 为什么用:开发环境可能有很多debug日志干扰
# 统计错误出现次数(量化分析)
grep -c "error" /var/log/messages
# -c (count):只输出匹配的行数,不显示内容
# 应用场景:判断问题的频率和严重程度
# 显示匹配的文件名(多文件搜索时)
grep -l "error" /var/log/*
# -l (list):只显示包含匹配内容的文件名
# 应用场景:快速定位哪些日志文件有问题
|
实战案例:SSH暴力破解分析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # 第一步:提取所有失败登录的IP
grep "Failed password" /var/log/secure | awk '{print $11}' | sort | uniq -c | sort -nr
# 分解说明:
# grep "Failed password":筛选认证失败记录
# awk '{print $11}':提取第11列(IP地址)
# sort:排序(为uniq做准备)
# uniq -c:统计每个IP出现的次数
# sort -nr:按数字降序排列(-n:数字排序, -r:逆序)
# 典型输出解读:
# 253 192.168.1.100
# 45 192.168.1.101
# IP 192.168.1.100 在日志中出现了253次,是主要攻击源
# 第二步:查看这些IP的详细攻击时间
grep "192.168.1.100" /var/log/secure | head -5
# 查看该IP的前5条记录,确认攻击模式
|
2. 排序与统计高级用法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| # 命令:sort /var/log/messages | uniq -c | sort -nr | head -20
# 完整含义:找出日志中最常出现的20种模式
# 分步解析:
1. sort /var/log/messages
- 先对整个文件排序(uniq只能处理相邻的重复行)
2. uniq -c
- 合并相邻的重复行
- -c:在每行前添加出现次数
- 输出示例:" 127 Nov 10 14:25:01 server crond[1234]: ..."
3. sort -nr
- -n:按数字大小排序(默认是字典序)
- -r:逆序排列(从大到小)
4. head -20
- 只显示前20行(最常见的前20种日志)
# 应用场景:快速识别系统的主要活动在做什么
# 例如发现"Out of memory"出现上千次,说明内存泄漏严重
|
Web日志分析案例:找出最多访问IP
1
2
3
4
5
6
7
8
| # 命令:awk '{print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -nr | head -10
# 详细解释:
# awk '{print $1}':提取访问日志的第一列(客户端IP)
# 后续命令同上,最终得到TOP 10访问IP
# 进阶:找出访问最频繁的URL
awk '{print $7}' /var/log/apache2/access.log | sort | uniq -c | sort -nr | head -10
# $7:通常表示HTTP请求中的URL路径
|
3. 时间戳分析实战
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 命令:sed -n '/14:00:00/,/14:30:00/p' /var/log/messages
# 含义:提取14:00:00到14:30:00之间的日志
# sed -n:安静模式,只打印匹配的行
# /start/,/end/:范围匹配,从开始模式到结束模式
# p:打印命令
# 为什么用sed而不是grep?
# - sed可以按行号或模式范围提取,适合连续时间段
# - grep只能匹配单个模式
# 更精确的时间分析(使用awk)
awk '$3>="14:00:00" && $3<="14:30:00" {print}' /var/log/messages
# $3>=:第三列(时间)大于等于14:00:00
# &&:逻辑与操作符
# {print}:满足条件时执行打印操作
|
四、journalctl 现代日志系统详解
journalctl是systemd时代的日志管理工具,功能远超传统syslog
1. 基础用法
1
2
3
4
5
6
7
8
9
| # 命令:journalctl
# 默认行为:显示所有日志,从最早到最新
# 特点:使用less作为分页器,支持所有less操作
# 退出:按q键
# 实时跟踪模式
journalctl -f
# -f (follow):类似tail -f,但功能更强大
# 优势:可以实时过滤,如 journalctl -f -u nginx
|
2. 按服务单元过滤(最常用)
1
2
3
4
5
6
7
8
9
10
11
12
13
| # 查看Nginx服务的所有日志
journalctl -u nginx
# -u (unit):指定systemd服务单元
# 为什么重要:传统日志需手动找文件,journalctl自动聚合
# 查看SSH服务的错误日志
journalctl -u sshd -p err
# -p err:只显示错误级别及以上的日志
# 日志级别:emerg(0), alert(1), crit(2), error(3), warning(4), notice(5), info(6), debug(7)
# 查看服务从启动到停止的所有日志
journalctl -u nginx --since "2024-11-10" --until "2024-11-11"
# --since/--until:时间范围过滤,支持多种格式
|
3. 进程与日志关联
1
2
3
4
5
6
7
8
| # 查看特定PID的日志
journalctl _PID=1234
# _PID:systemd的日志字段,精确匹配进程ID
# 应用场景:某个进程崩溃,查看它的所有历史日志
# 查看特定用户的日志
journalctl _UID=1000
# _UID:用户ID,查看某个用户的所有操作日志
|
4. 启动日志分析(排查启动问题神器)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # 列出所有启动记录
journalctl --list-boots
# 输出示例:
# -2 0f8c4c5f5d3a4e8a9b2c1d0e3f7a6b5c Mon 2024-11-09 ...
# -1 a1b2c3d4e5f678901234567890123456 Sun 2024-11-10 ...
# 0 c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f Mon 2024-11-11 ...
# 数字:启动ID,0表示当前启动,-1表示上一次
# 哈希:启动的唯一标识符
# 查看上一次启动的日志
journalctl -b -1
# -b:限制为启动日志
# -1:指定启动ID
# 查看某次启动的内核日志
journalctl -b 0 -k
# -k:只显示内核消息(类似dmesg)
|
5. 组合查询实战
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| # 查询Nginx在过去1小时的错误日志
journalctl -u nginx -p err --since "1 hour ago"
# 组合选项:
# -u nginx:服务过滤
# -p err:级别过滤
# --since:时间过滤
# 输出示例:
-- Logs begin at Mon 2024-11-11 08:00:00 CST, end at Mon 2024-11-11 14:30:12 CST. --
Nov 11 14:25:15 web01 nginx[1234]: 2024/11/11 14:25:15 [error] 1234#0: *5678 connect() failed (111: Connection refused) while connecting to upstream
# 解读:
# 时间戳 主机名 进程名[PID]: 具体错误消息
# [error]:错误级别
# 1234#0:进程ID和线程ID
# *5678:连接ID
|
五、实战案例分析详解
案例1:SSH登录失败完整排查流程
场景:发现服务器响应慢,怀疑有暴力破解
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
| # Step 1:统计失败登录次数
grep "Failed password" /var/log/secure | wc -l
# wc -l:统计行数(word count -lines)
# 如果数字很大(如>1000),说明确实存在暴力破解
# Step 2:找出攻击来源IP
grep "Failed password" /var/log/secure | awk '{print $11}' | sort | uniq -c | sort -nr | head -5
# $11的含义:在CentOS的secure日志中,IP地址通常是第11列
# 如果日志格式不同,先用head查看列数:head -1 /var/log/secure
# Step 3:查看攻击时间分布(判断是否持续攻击)
grep "192.168.1.100" /var/log/secure | awk '{print $1" "$2" "$3}' | uniq -c
# 输出示例:
# 50 Nov 10 14:2[0-9]:
# 50 Nov 10 14:3[0-9]:
# 说明每分钟50次尝试,是自动化攻击
# Step 4:查看是否有成功登录(判断是否已攻破)
grep "Accepted" /var/log/secure
# 如果找到了攻击IP的成功登录,说明威胁严重
# 应立即更换密码、检查后门
# Step 5:统计尝试的用户名
grep "Failed password" /var/log/secure | awk '{print $9}' | sort | uniq -c | sort -nr | head -10
# $9:通常是尝试登录的用户名
# 常见模式:root、admin、test等默认账户
|
案例2:Web服务502/503错误深度分析
场景:网站出现502 Bad Gateway错误
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
| # Step 1:确认Nginx错误日志位置
# 查看Nginx配置:grep "error_log" /etc/nginx/nginx.conf
# 通常为:/var/log/nginx/error.log
# Step 2:实时观察错误
tail -f /var/log/nginx/error.log
# 观察到的典型错误:
# connect() failed (111: Connection refused) while connecting to upstream
# 含义:Nginx无法连接到后端服务(PHP-FPM/应用服务器)
# Step 3:同时监控PHP-FPM日志(确保看到完整上下文)
journalctl -f -u nginx -u php-fpm
# -f:实时跟踪
# -u nginx -u php-fpm:同时显示两个服务的日志,按时间混合排序
# 为什么重要:可以同时看到Nginx的请求和PHP-FPM的处理
# Step 4:检查系统资源(可能原因)
journalctl -p warning | grep -E "memory|oom|kill"
# -p warning:查看警告及以上级别
# -E:扩展正则表达式
# 查找OOM(Out of Memory)错误,可能导致PHP-FPM被杀
# Step 5:分析错误频率
grep "2024/11/11" /var/log/nginx/error.log | awk '{print $2}' | cut -d: -f1,2 | uniq -c
# $2:日期字段,如2024/11/11
# cut -d: -f1,2:按冒号分割,取小时和分钟
# 输出示例:识别错误高发时段
# 50 14:25
# 30 14:26
|
案例3:磁盘I/O错误导致服务异常
场景:服务突然变慢,怀疑磁盘问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| # Step 1:查看内核日志中的硬件错误
dmesg | grep -i "error\|fail\|bad"
# dmesg:显示内核消息缓冲区
# -i:忽略大小写
# 典型输出:
# [12345.678] sd 0:0:1:0: [sdb] Add. Sense: Unrecovered read error
# Step 2:查看系统日志中的磁盘错误
journalctl -p err | grep -E "disk|I/O|sda|sdb"
# -p err:只显示错误级别
# -E:扩展正则,同时匹配多个关键词
# 典型输出:
# Nov 11 14:30:12 server kernel: Buffer I/O error on dev sdb1, logical block 123456
# Step 3:检查SMART状态(需要smartmontools)
smartctl -a /dev/sda | grep -E "Error|Fail|Reallocated"
# 如果看到"Reallocated_Sector_Ct"数值很大,说明磁盘有坏道
# Step 4:统计错误频率
journalctl --since "24 hours ago" | grep "I/O error" | wc -l
# 如果数量持续增长,说明故障在恶化,需要立即备份
|
案例4:服务启动失败根本原因定位
场景:systemctl start nginx失败
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
| # Step 1:查看服务状态(快速诊断)
systemctl status nginx
# 关键信息:
# Active: failed (Result: exit-code) # 服务已失败
# Process: 1234 ExecStart=/usr/sbin/nginx (code=exited, status=1/FAILURE)
# status=1:通用错误码
# Step 2:获取详细日志
journalctl -u nginx -n 50
# -n 50:显示最后50行(类似tail -50)
# 关键信息:通常会显示具体错误,如 "nginx: [emerg] bind() to 0.0.0.0:80 failed"
# Step 3:检查配置语法
nginx -t
# 为什么重要:90%的启动失败是配置错误
# 典型输出:
# nginx: [emerg] unknown directive "sever" in /etc/nginx/conf.d/site.conf:5
# 明确指出第5行有拼写错误(sever应为server)
# Step 4:查看启动过程中的所有日志
journalctl -u nginx --since "5 minutes ago" -o verbose
# -o verbose:详细输出,显示所有字段
# 包含:_SYSTEMD_UNIT, _PID, _UID等元数据
# Step 5:检查依赖服务
systemctl list-dependencies nginx
# 显示:nginx.service依赖于network.target
# 如果网络服务未启动,Nginx也会失败
|
六、日志分析脚本详解
自动化分析脚本(带详细注释)
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
31
32
33
34
35
36
37
38
39
40
41
42
| cat > /usr/local/bin/log_analyzer.sh << 'EOF'
#!/bin/bash
# 脚本功能:自动分析系统日志并生成报告
# 使用方法:./log_analyzer.sh
LOGFILE=/var/log/messages
DATE=$(date +%b\ %d) # 例如:Nov 11
REPORT=/tmp/log_report_$(date +%Y%m%d).txt
# 1. 基础统计
echo "=== 日志基础统计 ===" | tee $REPORT
echo "总错误数: $(grep -ci "error" $LOGFILE)" | tee -a $REPORT
# tee命令:同时输出到屏幕和文件
# -a:追加模式
# 2. 最频繁的10种错误(带上下文)
echo -e "\n=== TOP 10 错误模式 ===" | tee -a $REPORT
grep -i "error" $LOGFILE | sort | uniq -c | sort -nr | head -10 | tee -a $REPORT
# -e:允许使用转义字符(如\n换行)
# 3. 安全事件分析
echo -e "\n=== 安全事件统计 ===" | tee -a $REPORT
FAILED_LOGINS=$(grep -c "Failed password" /var/log/secure 2>/dev/null || echo "0")
# 2>/dev/null:错误重定向到黑洞(文件不存在时不报错)
# || echo "0":如果命令失败,显示0
echo "SSH失败登录次数: $FAILED_LOGINS" | tee -a $REPORT
# 4. 今天的警告日志
echo -e "\n=== 今日警告日志 ===" | tee -a $REPORT
grep -i "warning" $LOGFILE | grep "$DATE" | tail -5 | tee -a $REPORT
# tail -5:只显示最近5条,避免过多
# 5. 内存不足检查
echo -e "\n=== OOM Killer 活动 ===" | tee -a $REPORT
journalctl -p warning | grep -i "oom-killer" | tail -3 | tee -a $REPORT
# OOM Killer:内存不足时杀进程的机制
# 如果有输出,说明系统曾内存耗尽
echo -e "\n报告已生成: $REPORT"
EOF
chmod +x /usr/local/bin/log_analyzer.sh
|
脚本运行示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| ./log_analyzer.sh
# 输出解读:
=== 日志基础统计 ===
总错误数: 158
# 说明:系统共有158条错误记录,需要关注
=== TOP 10 错误模式 ===
45 Nov 11 14:25:01 server CRON[1234]: (root) CMD (/usr/local/bin/backup.sh)
32 Nov 11 14:26:12 server kernel: [UFW BLOCK] IN=eth0 OUT= MAC=...
# 解读:CRON任务出现45次,是正常的定时任务
# UFW BLOCK出现32次,是防火墙正常拦截
=== 安全事件统计 ===
SSH失败登录次数: 0
# 良好:没有暴力破解尝试
=== OOM Killer 活动 ===
# 为空:系统未发生内存耗尽
|
七、日志轮转机制详解
logrotate工作原理
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
| # 查看logrotate配置
cat /etc/logrotate.d/nginx
# 典型配置:
# /var/log/nginx/*.log {
# daily # 每天轮转一次
# missingok # 日志不存在时不报错
# rotate 52 # 保留52个旧日志(52天)
# compress # 压缩旧日志(gzip)
# delaycompress # 延迟压缩(下次轮转时压缩)
# notifempty # 日志为空时不轮转
# create 0640 nginx adm # 新日志权限和属主
# sharedscripts # 多个日志共享脚本
# postrotate # 轮转后执行的命令
# if [ -f /var/run/nginx.pid ]; then
# kill -USR1 $(cat /var/run/nginx.pid) # 通知Nginx重新打开日志
# fi
# endscript
# }
# 手动执行日志轮转(测试配置)
logrotate -d /etc/logrotate.d/nginx
# -d (debug):测试模式,不实际执行,显示详细过程
# 强制立即轮转
logrotate -f /etc/logrotate.d/nginx
# -f (force):强制执行,忽略时间条件
|
八、常见问题快速定位表(带解读)
| 问题现象 | 查看命令 | 关键输出解读 | 解决方案 |
|---|
| 系统启动失败 | journalctl -b -1 | 红色"FAILED"行 | 查看失败服务的依赖关系 |
| SSH无法登录 | tail -f /var/log/secure | “Connection closed by …” | 检查防火墙、SELinux |
| 磁盘空间不足 | df -h + du -sh /* | 100%使用率 | 清理大文件或扩展分区 |
| 内存耗尽 | journalctl -p err | grep oom | “Kill process” | 增加内存或优化应用 |
| CPU 100% | top + journalctl -p warning | “soft lockup” | 检查内核版本、驱动 |
| 网络超时 | grep "timeout" /var/log/messages | “Connection timed out” | 检查网络配置、DNS |
| 权限被拒绝 | grep "denied" /var/log/audit/audit.log | avc: denied | 调整SELinux策略 |
| 服务频繁重启 | journalctl -u <服务> --since "1 hour ago" | 多条"Starting…" | 检查配置、资源限制 |
| 数据库慢查询 | grep "slow query" /var/log/mysql.log | Query_time: 10.5s | 优化SQL或添加索引 |
| SSL证书过期 | grep "expired" /var/log/httpd/error_log | “certificate expired” | 更新证书 |
九、高级技巧与最佳实践
1. 日志格式标准化
1
2
3
4
5
6
| # 使用logger命令写入自定义日志
logger -t MYAPP -p user.warning "Database connection failed"
# -t:标签(tag),在日志中显示为进程名
# -p:优先级(facility.level)
# 在/var/log/messages中显示:
# Nov 11 14:30:00 server MYAPP: Database connection failed
|
2. 日志关联分析
1
2
3
4
5
6
| # 同时查看多个关联服务的日志(时间对齐)
journalctl -u nginx -u php-fpm --since "10 minutes ago" -o short
# -o short:短格式,只显示时间和服务名,便于对比
# 输出示例:
# 14:25:10 web01 nginx[1234]: GET /api/user
# 14:25:11 web01 php-fpm[5678]: PHP Fatal error:...
|
3. 性能分析
1
2
3
4
5
| # 统计每秒日志条数(判断系统负载)
journalctl --since "1 hour ago" | awk '{print $3}' | cut -d: -f1,2,3 | uniq -c | sort -nr | head
# 输出解读:
# 500 14:25:30
# 表示在14:25:30这一秒内有500条日志,系统可能异常繁忙
|
4. 日志远程传输(集中管理)
1
2
3
4
5
| # 配置rsyslog发送到远程服务器
echo '*.* @@192.168.1.200:514' >> /etc/rsyslog.conf
# @@:TCP协议(@为UDP)
# 514:syslog默认端口
systemctl restart rsyslog
|
总结建议:
- 理解日志结构:时间戳、主机名、进程名、消息体四部分
- 善用管道组合:grep+awk+sort+uniq是黄金组合
- 重视上下文:错误前5行和后5行往往有关键线索
- 时间范围最关键:先确定问题发生时间,再精确提取
- 从全局到局部:先用journalctl看整体,再用grep精确定位
掌握这些,你就能像资深运维一样快速诊断90%的Linux问题!