日志查询"四大剑客" + 实战补强:head / tail / less / more 一篇吃透
生产环境的日志动辄几十 G,一个cat就能让你的 SSH 终端"自闭"。这篇文章帮你把 Linux 看日志的正确姿势捋清楚,并补上原资料没讲到的压缩日志、journalctl、grep 联动、awk 切片等实战玩法。关键词:head · tail · less · more · journalctl · zless · grep · 实时跟踪
一、先说结论:为什么不要用 cat / vim 看日志?
很多新手第一次排查问题时下意识就敲:
cat /var/log/app/server.log vim /var/log/nginx/access.log——然后终端开始疯狂滚屏,或者整台机器内存飙红。原因很简单:
| 命令 | 行为 | 大文件后果 |
|---|---|---|
cat | 把整个文件一次性写到 stdout | 刷屏停不下来,Ctrl+C 都救不回光标 |
vi/vim | 把整个文件从磁盘全部加载进内存 | 30G 日志直接 OOM,机器卡死 |
nano | 同上,且更卡 | 不推荐 |
✅正确做法:用按行/按页流式读取的工具,不占内存:
head / tail / less / more —— 日志查询四剑客
二、head:看文件开头
2.1 用法
head [选项] 文件| 选项 | 含义 |
|---|---|
-n NUM | 显示前 NUM 行(默认 10 行) |
-c NUM | 显示前 NUM 字节 |
-q | 多文件时不打印文件名头 |
-v | 始终打印文件名头 |
2.2 案例:显示前 5 行
# 三种写法等价 head -n5 /etc/passwd head -n 5 /etc/passwd head -5 /etc/passwd💡温馨提示:日常
-数字最快;某些精简系统(busybox / Alpine)只支持-n NUM,遇到报错改回-n5即可。
2.3 看前 1KB 内容
head -c 1024 /var/log/app/server.log三、tail:看文件结尾(运维出场率最高)
3.1 用法
| 选项 | 含义 |
|---|---|
-n NUM | 显示最后 NUM 行(默认 10 行) |
-f | follow,持续输出新写入的内容(看日志神器) |
-F | follow + 文件被 rotate 后自动重新打开(强烈推荐) |
--pid=PID | 当指定进程退出后自动结束 tail |
-c NUM | 最后 NUM 字节 |
3.2 案例:显示后 5 行
tail -n5 /etc/passwd tail -5 /etc/passwd3.3 案例:实时跟踪日志
# 经典写法 tail -f /var/log/secure # 推荐写法(应对 logrotate) tail -F /var/log/nginx/access.log实测建议:打开两个终端,一个跑
tail -F,另一个触发动作(登录、发请求等),就能直观看到日志滚动。
3.4 赠送命令
tailf /var/log/messages # 等价于 tail -f,但已被多数发行版废弃,建议直接用 tail -F3.5 补充:进阶组合拳
# 看最后 1000 行里包含 ERROR 的 tail -n 1000 server.log | grep -i error # 实时跟踪并高亮关键字 tail -F app.log | grep--color=always -E 'ERROR|WARN|$' # 实时只看 5xx 响应 tail -F /var/log/nginx/access.log | grep ' 5[0-9]{2} ' # 跟踪到进程结束自动退出 tail --pid=$(pgrep -f myapp) -F app.log四、less:分页浏览的王者
less比more更强大(俗话:less is more, more than more)。它不预读整个文件,所以哪怕 100G 也能秒开。
4.1 常用快捷键
| 快捷键 | 作用 |
|---|---|
q | 退出 |
空格/f | 下一页(forward) |
b | 上一页(back) |
↓/↑ | 单行滚动 |
g | 跳到第 1 行 |
G | 跳到最后 1 行 |
99g | 跳到第 99 行 |
/关键字 | 向下搜索,n下一个,N上一个 |
?关键字 | 向上搜索 |
&关键字 | 只显示匹配行(超好用) |
F | 类似tail -f,按 Ctrl+C 退出跟踪 |
h | 帮助 |
4.2 常用选项
less -N file # 显示行号 less -S file # 长行不换行(看 JSON / 一行很长的日志特别有用) less -i file # 搜索时忽略大小写 less +F file # 启动即进入 tail -f 模式 less +G file # 直接跳到末尾4.3 实战小技巧
# 边读压缩文件边分页(不用先解压) zless /var/log/app/server.log.2024-06-01.gz xzless server.log.xz bzless server.log.bz2 # 看 systemd 日志带分页 journalctl -u nginx | less五、more:分页浏览的"老前辈"
more file- 按
空格翻页,按回车翻一行 - 到达文件末尾会自动退出(不能往回翻)
- 没有
less的搜索、行号、跟踪等功能
⚠️ 现代 Linux 一律推荐less,more只在最小化镜像或老旧 UNIX 里用。
六、四剑客对比速查
| 命令 | 适用场景 | 是否可向上翻 | 是否实时跟踪 | 是否支持搜索 |
|---|---|---|---|---|
head | 看文件开头 | — | ❌ | ❌ |
tail | 看文件结尾 / 实时跟踪 | — | ✅-f/-F | ❌(配合 grep) |
less | 分页浏览大文件 | ✅ | ✅F模式 | ✅/``? |
more | 简单分页浏览 | ❌ | ❌ | 有限 |
口诀:“头 head,尾 tail,长文翻看用 less,more 只是备胎”。
七、补充:生产必备的几把"暗器"
7.1 grep / egrep / rg —— 关键字过滤
grep -i 'error' app.log # 忽略大小写 grep -n 'timeout' app.log # 显示行号 grep -c 'ERROR' app.log # 统计出现次数 grep -v 'DEBUG' app.log # 反向匹配(排除 DEBUG) grep -A3 -B1 'Exception' app.log # 命中行前 1 后 3 行(上下文) grep -r 'panic' /var/log/ # 递归整个目录 grep-E 'ERROR|FATAL' app.log # 扩展正则(或)性能更猛的替代品(推荐安装):
rg 'OutOfMemory' /var/log/ # ripgrep,比 grep 快几倍,自动跳过二进制 ug 'pattern' file # ugrep,支持模糊匹配7.2 awk —— 按列提取与统计
# 统计每个 IP 的访问次数 Top 10(access.log 标准格式) awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10 # 统计每个 HTTP 状态码出现次数 awk '{print $9}' access.log | sort | uniq -c | sort -rn # 计算某接口平均响应时间(假设第 11 列是耗时 ms) awk '$7=="/api/order"{sum+=$11; n++} END{print sum/n" ms"}' access.log sort:对第一行输入的ip进行排序 uniq:统计重复项 sort -rn:按照前面统计出的访问次数从高到低重新排序。实例如下: 1. 先创建测试日志 access.log 执行命令生成测试内容: bash 运行 cat > access.log << EOF 192.168.1.10 - - [24/Jun/2026:10:00:00] "GET /index.html" 200 192.168.1.20 - - [24/Jun/2026:10:00:01] "GET /api" 200 192.168.1.10 - - [24/Jun/2026:10:00:02] "GET /index.html" 200 192.168.1.30 - - [24/Jun/2026:10:00:03] "GET /test" 200 192.168.1.10 - - [24/Jun/2026:10:00:04] "GET /index.html" 200 192.168.1.20 - - [24/Jun/2026:10:00:05] "GET /api" 200 192.168.1.10 - - [24/Jun/2026:10:00:06] "GET /index.html" 200 192.168.1.30 - - [24/Jun/2026:10:00:07] "GET /test" 200 192.168.1.30 - - [24/Jun/2026:10:00:08] "GET /test" 200 192.168.1.30 - - [24/Jun/2026:10:00:09] "GET /test" 200 EOF 2. 分步拆解演示 第一步:awk '{print $1}' access.log 提取每行第一列(IP) bash 运行 awk '{print $1}' access.log 输出: plaintext 192.168.1.10 192.168.1.20 192.168.1.10 192.168.1.30 192.168.1.10 192.168.1.20 192.168.1.10 192.168.1.30 192.168.1.30 192.168.1.30 第二步:加管道 | sort 按字符排序,把相同 IP 凑到一起 bash 运行 awk '{print $1}' access.log | sort 输出: plaintext 192.168.1.10 192.168.1.10 192.168.1.10 192.168.1.10 192.168.1.20 192.168.1.20 192.168.1.30 192.168.1.30 192.168.1.30 192.168.1.30 第三步:再加 | uniq -c 统计相邻重复行的次数,格式:次数 IP bash 运行 awk '{print $1}' access.log | sort | uniq -c 输出: plaintext 4 192.168.1.10 2 192.168.1.20 4 192.168.1.30 第四步:再加 | sort -rn 按数字大小倒序排序(访问次数从高到低) bash 运行 awk '{print $1}' access.log | sort | uniq -c | sort -rn 输出: plaintext 4 192.168.1.30 4 192.168.1.10 2 192.168.1.20 第五步:最后 | head -10 取前 10 行(本例只有 3 行,全部展示) bash 运行 awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10 最终结果: plaintext 4 192.168.1.30 4 192.168.1.10 2 192.168.1.20 总结 192.168.1.10、192.168.1.30 各访问 4 次,频次最高 192.168.1.20 访问 2 次 完全实现了「统计访问 IP 频次并取 TOP10」的需求。7.3 sed —— 流式编辑 / 提取
sed -n '100,200p' app.log # 只看第 100–200 行 sed -n '/START/,/END/p' app.log # 提取两个标记之间的内容 sed -i 's/旧词/新词/g' file # 批量替换(生产慎用!先备份)7.4 journalctl —— systemd 时代的"全局日志"
现在大多数发行版(RHEL 7+/Ubuntu 16.04+)的服务日志默认走systemd-journald,不再单独写文件,得用journalctl:
journalctl # 全部日志 journalctl -u nginx.service # 只看 nginx 单元 journalctl -u nginx -f # 实时跟踪(相当于 tail -f) journalctl --since "2026-06-12 09:00"--until "2026-06-12 10:00" journalctl -p err # 只看 error 及以上级别 journalctl -k # 内核日志(dmesg 的升级版) journalctl --disk-usage # 看 journal 占用多大磁盘 journalctl --vacuum-time=7d # 只保留最近 7 天7.5 压缩日志 —— z 系列家族
logrotate滚动后的日志通常是.gz/.xz/.bz2,别先解压,直接用:
| 原命令 | 压缩版 |
|---|---|
cat | zcat/xzcat/bzcat |
less | zless/xzless/bzless |
grep | zgrep/xzgrep/bzgrep |
diff | zdiff |
zgrep -i 'oom' /var/log/messages-*.gz7.6 多文件 / 多机日志聚合
# 同时跟踪多个文件 tail -F /var/log /nginx/{access,error}.log # 多机日志聚合(推荐工具) # - ELK / EFK:Elasticsearch + Logstash/Fluentd + Kibana # - Loki + Grafana:轻量、便宜、对 K8s 友好 # - ClickHouse + Vector:海量日志高性能分析八、避坑清单(生产建议)
- ❌不要
cat huge.log,✅ 改用less或tail -n 500 - ❌不要
vim huge.log,✅ 用view huge.log(只读,但同样会全量加载,仍不推荐)或less - ⚠️谨慎
grep -r在/,可能扫到/proc、/sys,加--exclude-dir - ✅ 实时跟踪一律用
tail -F,不用tail -f(防止 logrotate 后丢日志) - ✅ 给日志配
logrotate,并设置compress、maxage,免得撑爆磁盘 - ✅ 重要服务接入集中式日志(Loki / ELK),别只靠登机
grep - ✅ 排查问题先
df -h /var/log看磁盘,再du -sh *找最大日志 - ✅ 涉及敏感字段(手机号、身份证、token)做脱敏后再外发
九、示例脱敏说明
文中所有日志路径、IP、用户名均为通用示例,与任何真实生产系统无关。
| 字段类型 | 示例脱敏写法 |
|---|---|
| IP 地址 | 192.0.2.x/198.51.100.x(RFC 5737 文档示例段) |
| 手机号 | 138****0000 |
| 邮箱 | user@example.com |
| 用户名 | user001/admin_demo |
| 路径 | /var/log/app/xxx.log |
公开排障截图前,记得用
sed/awk批量替换敏感字段,例如:sed -E 's/1[3-9][0-9]{9}/138****0000/g; s/([0-9]{1,3}\.){3}[0-9]{1,3}/192.0.2.x/g' raw.log > safe.log
十、一句话总结
看日志,不刷屏、不爆内存:head 看头、tail 追尾、less 翻页、grep/awk 上场。系统日志走 journalctl,压缩日志加个 z 前缀,集中分析交给 Loki / ELK。
如果对你有帮助,欢迎点赞 / 在看 / 转发给身边正在被日志虐的运维同行
**
**
**
**
linux · 目录
上一篇Vim 编辑器从入门到上瘾:一篇文章搞定 Linux 程序员的"瑞士军刀"下一篇打包压缩"三剑客" + 现代补强:tar / gzip / zip 一篇全掌握(含 zstd / pigz / 7z 实战)
阅读 10
留言
写留言