文本查看与搜索
Linux 运维基础 · 第六章 目标:掌握从海量日志中快速定位目标信息的能力
1. 概述#
运维的日常就是:日志、日志、日志。服务挂了 — 看日志;性能慢了 — 看日志;用户说登录不了 — 看日志。本章覆盖从"打开文件看一眼"到"在几 GB 的日志里秒定位问题行"的全部技能。
核心工具链:cat/less/head/tail 负责查看,grep 负责搜索,正则表达式负责精确匹配。
2. 查看文件内容#
2.1 cat — 全量输出#
bash
cat file.txt # 全量输出到终端
cat -n file.txt # 带行号输出
cat file1.txt file2.txt > merged.txt # 合并多个文件注意:不要在几百 MB 的日志上用 cat——它会一次性全量输出,终端卡死是小事,远程 SSH 带宽被打满才麻烦。大文件用 less。
2.2 less — 分页浏览(运维首选)#
bash
less /var/log/syslog # 打开文件,分页浏览
# less 内的快捷键(和 man/more 共用)
# Space / b 向下翻页 / 向上翻页
# g / G 跳到文件开头 / 文件末尾
# /keyword 向下搜索
# ?keyword 向上搜索
# n / N 下一个匹配 / 上一个匹配
# q 退出
# -N 启动参数 显示行号
# -i 启动参数 搜索忽略大小写
less -N /var/log/syslog # 显示行号
less +F /var/log/syslog # 类似 tail -f,实时跟踪
# 在 less 中按 Ctrl+C 停止跟踪,按 F 恢复跟踪2.3 head / tail — 看头看尾#
bash
# head:看文件开头
head -n 20 /var/log/syslog # 前 20 行
head /var/log/syslog # 不带 -n 时默认前 10 行
# tail:看文件末尾
tail -n 50 /var/log/syslog # 最后 50 行
tail -n +100 file.txt # 从第 100 行开始到末尾
# tail -f:实时跟踪(最重要)
tail -f /var/log/syslog # 实时看日志增长
tail -f /var/log/syslog /var/log/auth.log # 同时跟踪多个文件
tail -n 100 -f /var/log/syslog # 先显示最后 100 行,再实时跟踪3. grep:文本搜索的核心#
grep 是运维的"搜索工具"。日志排查、配置审计、进程过滤——到处都用。
3.1 基本用法#
bash
grep "error" /var/log/syslog # 在文件中搜索
grep "error" *.log # 搜索多个文件
grep "error" /var/log/* # 通配符3.2 核心参数#
| 参数 | 含义 | 使用场景 |
|---|---|---|
-i | 忽略大小写 | grep -i "error" 能匹配 Error/ERROR/error |
-r | 递归搜索目录 | grep -r "502" /var/log/nginx/ |
-n | 显示行号 | grep -n "timeout" app.log 直接定位到第几行 |
-v | 反向匹配(不包含) | grep -v "DEBUG" app.log 过滤掉 DEBUG 行 |
-c | 统计匹配行数 | grep -c "ERROR" app.log 有多少行包含 ERROR |
-E | 扩展正则表达式 | grep -E "error|timeout|failed" 或的关系 |
-w | 精确匹配整个单词 | grep -w "err" 不匹配 "error",只匹配独立的 "err" |
-A N | 显示匹配行及后面 N 行 | grep -A 5 "Exception" 看异常的调用栈 |
-B N | 显示匹配行及前面 N 行 | grep -B 2 "ERROR" 看错误前发生了什么 |
-C N | 显示匹配行及前后 N 行 | grep -C 3 "timeout" 看完整的上下文 |
-l | 只显示文件名 | grep -rl "TODO" src/ 列出所有包含 TODO 的文件 |
-o | 只输出匹配的部分(不输出整行) | grep -oE '[0-9.]+' access.log 只把 IP 抠出来,配合 sort/uniq 统计 |
-F | 固定字符串匹配(不解析正则) | grep -F '1.2.3.4' f:点号当字面量,快且不怕特殊字符 |
-P | Perl 兼容正则(PCRE) | grep -P '\d{3}' 支持 \d \w \s、断言、非贪婪 *? |
--color | 高亮匹配关键词 | 多数系统默认开启(--color=auto) |
3.3 常用组合#
bash
# 递归搜索:在所有 Nginx 日志中找 502 错误
grep -rn "502 Bad Gateway" /var/log/nginx/ # r=递归, n=行号
# 上下文:看 ERROR 前 3 行 + 后 5 行
grep -B3 -A5 "ERROR" app.log
# 排除干扰:找 ERROR 但排除已知的无关错误
grep "ERROR" app.log | grep -v "known_ignore_pattern"
# 统计:看每种错误出现了多少次
grep "ERROR" app.log | awk '{print $NF}' | sort | uniq -c | sort -rn
# 多条件或:找 error 或 timeout 或 failed
grep -E "error|timeout|failed" app.log
grep -e "error" -e "timeout" -e "failed" app.log # 等价写法
# 排除注释和空行:只看有效配置
grep -v "^#" /etc/nginx/nginx.conf | grep -v "^$"
# "^#" 行首是 # 的注释行,"^$" 是空行4. 正则表达式入门#
配合 grep、sed、awk 使用正则,威力翻倍。
4.1 三种流派:BRE / ERE / PCRE(最大的坑)#
正则不是"一种"语法,Linux 下有三套,grep 用不同参数切换:
| 流派 | grep 参数 | 说明 |
|---|---|---|
| BRE(基础正则) | grep(默认) | + ? { } | ( ) 是普通字符,要当元字符必须转义成 \+ \? \{ \} \| \( \) |
| ERE(扩展正则) | grep -E | + ? { } | ( ) 直接就是元字符,不用转义(想匹配字面量才转义) |
| PCRE(Perl 正则) | grep -P | ERE 基础上再加 \d \w \s、(?=...) 断言、*? 非贪婪等 |
易错点:同一个意图,BRE 和 ERE 的写法正好相反。
bash
# 匹配 "abc 或 abbc"(b 出现 1 次以上)
grep 'ab\+c' f # BRE:+ 要转义
grep -E 'ab+c' f # ERE:+ 直接用
# 分组 + 或
grep '\(err\|warn\)' f # BRE:() 和 | 都要转义
grep -E '(err|warn)' f # ERE:干净利落
# 记忆:ERE 里“加了反斜杠反而变回字面量”。写正则优先用 grep -E,省心。
. * [ ] ^ $在 BRE / ERE 里行为一致,不用管流派;出问题的永远是+ ? { } | ( )。 PCRE(-P)依赖 libpcre,极简系统(BusyBox)可能没有;这时退回-E。
4.2 基础元字符#
下表按 ERE(
grep -E) 语法列出。若用默认 BRE,+ ? { } | ( )这几行需按上表加反斜杠。
| 元字符 | 含义 | 示例(ERE) |
|---|---|---|
. | 匹配任意单个字符 | h.t 匹配 hat/hit/hot |
* | 前一个字符出现 0 次或多次 | ab*c 匹配 ac/abc/abbc |
+ | 前一个字符出现 1 次或多次 | ab+c 匹配 abc/abbc(BRE 写 ab\+c) |
? | 前一个字符出现 0 次或 1 次 | ab?c 匹配 ac/abc(BRE 写 ab\?c) |
[] | 字符类,匹配方括号内任意字符 | [Hh]ello 匹配 Hello/hello |
[^] | 否定字符类 | [^0-9] 非数字的字符 |
^ | 行首 | ^ERROR 行首的 ERROR |
$ | 行尾 | done$ 行尾的 done |
| | 或 | error|timeout(BRE 写 error\|timeout) |
() | 分组 | (error|timeout)(BRE 写 \(error\|timeout\)) |
\ | 转义 | \. 匹配字面的点 |
{n,m} | 前一个字符出现 n 到 m 次 | [0-9]{2,4} 匹配 2-4 位数字(BRE 写 \{2,4\}) |
4.3 运维常用正则示例#
bash
# 匹配 IP 地址(简化版)
grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' access.log
# 匹配时间戳格式 [01/Jul/2025:10:30:15]
grep -E '\[[0-9]{2}/[A-Z][a-z]{2}/[0-9]{4}:[0-9]{2}:[0-9]{2}:[0-9]{2}' access.log
# 匹配 HTTP 状态码(三位数)
grep -E ' [0-9]{3} ' access.log
# 匹配以 ERROR 或 FATAL 开头的行
grep -E '^(ERROR|FATAL)' app.log
# 匹配行尾是分号或逗号
grep -E '[,;]$' data.txt
# 匹配包含数字 >= 500 的行(简化)
grep -E '5[0-9]{2}' access.log5. 实战场景#
实战 1:实时监控错误日志#
bash
# 场景:服务刚上线,需要实时看有没有错误
# 方法 1:tail -f + grep
tail -f /var/log/myapp/app.log | grep -i "error"
# 方法 2:同时高亮多个关键词
tail -f /var/log/myapp/app.log | grep -E --color "error|timeout|exception|fatal"
# 方法 3:看错误的同时排除噪音
tail -f /var/log/myapp/app.log | grep -i "error" | grep -v "DEBUG\|known_bug"实战 2:排查 Nginx 502 错误#
bash
# Step 1:确认 502 的范围和时间分布
grep -rn "502" /var/log/nginx/ | wc -l
# 一共多少条 502
# Step 2:看最近 10 条 502
grep "502" /var/log/nginx/access.log | tail -10
# Step 3:502 对应的 upstream 是哪台
grep "502" /var/log/nginx/error.log | tail -10
# 看到 upstream: "http://10.0.1.5:8080/..."
# Step 4:统计哪些 URI 出 502 最多
grep " 502 " /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head
# 找到最频繁出 502 的接口路径
# Step 5:统计出 502 最多的客户端 IP(grep -o 组合拳)
grep " 502 " /var/log/nginx/access.log \
| grep -oE '^[0-9]{1,3}(\.[0-9]{1,3}){3}' \
| sort | uniq -c | sort -rn | head
# grep -oE 只抠出行首 IP → sort 排序 → uniq -c 计数 → sort -rn 倒序 → head 取 TopN
# 这套“grep|sort|uniq -c|sort -rn|head”是日志分析的万能组合拳实战 3:找 K8s Pod 日志中的错误#
bash
# 看 Pod 最近 200 行日志中的 ERROR
kubectl logs pod-name --tail=200 | grep ERROR
# 看 Pod 日志,实时过滤错误
kubectl logs -f pod-name | grep -E "ERROR|FATAL|Exception"
# 看多个 Pod(标签筛选)的日志
kubectl logs -l app=myapp --tail=100 | grep -i error6. 性能提示#
bash
# 大文件搜索:不要 cat 全量再 pipe grep(极慢)
cat 10GB.log | grep "error" # 错误!cat 读全部再传给 grep
# 正确方式:让 grep 直接读文件
grep "error" 10GB.log # grep 内部做了优化
# 递归搜索大目录时加限制
grep -rn "error" /var/log/ # 小心遍历所有子目录
grep -rn "error" /var/log/nginx/ # 限制范围
# 如果知道文件后缀,加 --include
grep -rn "error" /var/log/ --include="*.log"7. 查看工具速查表#
| 命令 | 用法 | 适用场景 |
|---|---|---|
cat | cat file.txt | 几十行的小文件 |
cat -n | cat -n file.txt | 小文件+需要行号 |
less | less huge.log | 大文件、分页浏览 |
less +F | less +F file.log | 打开后自动实时跟踪 |
head -n | head -n 20 file | 只看开头几行 |
tail -n | tail -n 50 file | 只看末尾几行 |
tail -f | tail -f app.log | 实时跟踪日志增长 |
其他实用查看命令#
bash
# wc:统计行数、单词数、字节数
wc -l access.log # 日志有多少行
wc -c file.txt # 文件多少字节
find . -name "*.go" -exec cat {} + | wc -l # 项目总代码行数
# file:判断文件类型
file unknown_file # 不确定是什么文件时用这个
file /bin/ls # ELF 64-bit executable
# stat:查看文件的详细元数据
stat /etc/passwd
# 看 inode、权限、三个时间戳(atime/mtime/ctime)8. 小结#
| 知识点 | 一句话记忆 |
|---|---|
| 查看 | 小文件 cat -n,大文件 less,实时 tail -f |
| grep 核心 | -rn 递归+行号,-v 排除,-o 只出匹配串,-A/-B/-C 上下文 |
| 正则流派 | 默认 BRE(+?{}|() 要转义),-E 用 ERE(不转义),-P 用 PCRE |
| 正则元字符 | . 任意字符,* 0-N 次,[] 字符类,^ 行首,$ 行尾 |
| 不要 cat 大文件 | grep 直接读文件更快 |