ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux日志查看命令实战:tail、less、grep、sed高效排查

Linux日志查看命令实战:tail、less、grep、sed高效排查 简介这是一份面向Linux运维与开发人员的日志查看速查手册系统整理了tail/head、cat/tac、less/more、grep/sed、wc等常用命令的典型用法与组合技巧。资源以PDF格式呈现共1个文件压缩包体积仅57KB轻量便携适合随时查阅。目前已吸引3138人学习下载是日常排查服务器日志、快速定位异常的高频工具总结。内容从实时监控日志增长的tail -f到分页浏览的less与more再到基于正则匹配的grep搜索和流编辑工具sed每类命令都配有参数说明和实际使用场景。尤其针对生产环境常见需求给出了按时间段过滤日志、查看关键字上下文、统计关键字出现行数、实时跟踪错误日志等组合示例能帮助读者从只会简单查看进阶到高效分析日志、精准定位故障。无论是初次接触Linux日志的新手还是需要提升排障效率的资深工程师都能从中获得即查即用的命令参考。1. 从“看日志”到“捞日志”先选对命令组排查线上问题时最耗时间的往往不是定位代码逻辑而是从几十 GB 的日志里捞出真正有用的那几十行。很多人在这一步习惯性用cat grep文件一大就直接把终端卡死还有人用tail -f盯了半天结果程序崩溃的信息早被滚屏冲掉了。Linux 日志查看命令并不复杂真正拉开效率差距的是你得知道每个工具擅长解决什么tail/head管首尾与实时追踪less管大文件浏览与定位grep/sed管过滤与切片wc管统计。本文把这四组命令的参数细节和组合用法拆开讲重点落在“查某个时间段的日志、取最后一次命中的上下文、实时过滤关键字”这三个高频场景上读完可以直接照着操作。2. 从头尾读起tail/head 与 cat/tac 的分工和边界2.1 tail 不只是看末尾-f 与 -F 的取舍tail最常用的场景是看日志文件的尾部内容但很多人混淆了-f和-F这两个参数。tail -f filename是实时追踪文件新增内容常用于监控正在写入的日志比如应用在持续输出 access log 时。它有个坑如果日志文件被轮转过logrotate 把文件重命名、新文件顶上来tail -f会继续盯着旧文件的句柄监控就断了。tail -F则是按文件名重新打开文件被轮转后会自动跟到新文件上。生产环境里我建议统一用tail -F尤其是在日志会按天或按大小切割的场景否则会出现“日志还在写但终端已经不动了”的假象。# 实时监控日志文件轮转后仍然保持跟踪 tail -F /var/log/app/application.log # 实时监控并仅显示最后 30 行适合刚接上手想先看最近状态 tail -30F /var/log/app/application.logtail -F后面的数字表示初始显示多少行我习惯把它放在-F前面语义上是“先回看 30 行然后持续跟随”。注意区分tail -n 30和tail -30是等价的但tail -n 30是完全不同的含义它表示从第 30 行开始显示直到文件末尾这里号代表“行号起点”不是“偏移量”。很多人刚接触时容易把这个和“往后多少行”搞混写脚本时尤其要留心tail -n 100输出的是第 100 行以及后面的内容不是“最后 100 行之后的内容”这种模糊描述。2.2 head/tail 行号参数理解“相对位置”语义head和tail的行号参数都支持正负号但语义相反放在一起对比才不容易犯晕。# 查看前 100 行 head -n 100 app.log # 查看除最后 100 行之外的所有内容即前 N-100 行N 为文件总行数 head -n -100 app.log # 查看第 100 行之后的所有内容 tail -n 100 app.log # 查看最后 100 行 tail -n 100 app.log逻辑说明head -n -100的-100表示“排除尾部 100 行”这对日志里尾部正好是异常堆栈、想忽略掉时很有用tail -n 100的100表示“从第 100 行开始输出”。注意head -n 100和head -n 100的效果一样都表示显示前 100 行号在 head 中不做起点解释这里两个命令的参数语义不对称容易记混建议以“tail 的 号等价于从第 N 行起读”为唯一记忆锚点。2.3 cat/tac 的顺序视角与 -n 编号cat的定位是“一次性输出整个文件”用于小文件直接看全貌或者和管道配合做行号编号。cat -n filename会给每一行加行号输出这个和grep -n的行号语义一致都是“第几行”方便后续精确引用。tac是cat的反序版本按行倒序输出即文件的最后一行变成输出的第一行。它的用途不是单纯“倒着看”而是配合head实现“看末尾 N 行且带上下文”的需求。例如排错时想快速看一个几 GB 日志文件最后 100 行内容可以直接tac huge.log | head -n 100这不依赖文件大小预读输出速度快比tail更灵活的地方是你可以再管道接grep或sed做二次处理而tail -n的输出同样能接管道但语义上tac更适合“从后往前扫一遍”的排查场景。# 带行号查看文件全部内容 cat -n app.log | tail -n 100 | head -n 20 # 从后往前输出最后 50 行并过滤 WARN 关键字 tac app.log | head -n 50 | grep WARNcat -n之后接tail再接head的做法本质上是先给所有行编号再提取第 100 到第 120 行。开销在于cat -n需要全文件扫描大文件不推荐此场景更合适的工具是sed它在第 4 章展开。tac对超大文件能快速出尾部内容因为大多数文件系统对按序读尾部数据友好且不需要把整文件加载到内存这点在内存受限的跳板机上很有优势。3. 翻页与定位less 才是日志浏览的正确姿势3.1 less 与 more交互能力决定选择more是最早的分页工具只能向下翻且翻过的地方不能再回看在日志排查中作用非常有限。less设计上就定位为“反向兼容 more 且更强大”支持上下方向键、翻页、搜索、跳转到指定行、前后移动等交互操作。更关键的是less默认不会把整个文件读进内存它是一页一页按需读取的打开一个 10 GB 的日志文件也能秒开。这个特性在查看超大日志时是刚需很多人卡在vim打开大文件半天没响应换成less就好了。# 打开日志文件并显示行号 less -N app.log-N参数会在左侧显示行号但注意这个行号是less自己计算的逻辑行号不是文件里的物理行号和cat -n的结果在常规文件上是一致的。按住g跳到文件首行按G跳到文件尾行这两个键位常用且免记。3.2 启动定位参数让文件一打开就停在目标位置# 打开文件并直接定位到第 100 行 less 100g app.log # 打开文件并直接定位到最后一行 less G app.log # 打开文件并从上往下第 100200000 字节处开始显示 less 100200000b app.log参数说明后面跟的是less的内部命令100g是“跳转到第 100 行”G是“跳转到文件末尾”b后缀代表字节偏移。字节定位适合日志文件中一行数据特别长比如打印了完整 JSON 报文的场景行号定位不够精确字节定位能跳过前段噪声直接看中后段。实际使用中less 100g的启动速度比启动后再按100g更快因为它在初始化时就设置好位置不会先渲染第一屏再跳转。3.3 在 less 内部搜索与跳转less的搜索语法和vim类似打开文件后直接输入/加关键字回车就能从上往下搜索按n跳到下一个匹配项按NShiftn跳到上一个匹配项。搜索支持正则表达式例如/ERROR|Exception可以同时匹配两种错误关键字。这里有个容易被忽略的技巧less /keyword app.log在启动时就直接定位到第一个匹配keyword的行适合快速查看某类错误第一次出现的日志段落。# 打开日志并定位到第一个 ERROR 出现的位置 less /ERROR app.log # 打开日志搜索 WARN 关键字并按字节位定位到 50% 位置 #先输入 /WARN 再输入 50p 进行跳转 less 50p app.log说明50p中的p是百分比定位不是字节定位表示打开文件时把视图定位到整个文件的 50% 处。50%处的对应行在日志文件中大致等于时间轴的中间位置如果日志按时间顺序写入这能快速找到一个排查时间段的起点。less /ERROR的优点是启动即命中缺点是只定位到第一个匹配项如果想要逐个浏览所有 ERROR 出现的上下文用上面的/ERROR加n键翻查更合适。4. 过滤与流式处理grep/sed 把大日志变窄4.1 grep 的检索参数细节-w、-A/-B/-C 与 -ogrep的核心能力是“按模式筛选行”但直接grep keyword file.log只给命中行不展示上下文排查异常堆栈时远远不够。实际工作中我常配合-C上下文行数一起用。-A是 after显示匹配行之后的 N 行-B是 before显示之前的 N 行-C则同时显示前后 N 行。-w强制全词匹配避免grep Error把ErrorCode、Errors也搜进去这在代码里关键字非常常见。# 精确匹配 error 单词并显示前后 5 行输出带行号、颜色标记 grep -w error app.log -C 5 -n --coloralways | less -R # 只输出匹配到的内容而不是整行适合提取 IP、订单号 grep -o -E [0-9]\.[0-9]\.[0-9]\.[0-9] app.log | sort | uniq -c--coloralways在管道传给less时会让 ANSI 颜色转义码传递过去less -R能正确解析并显示颜色否则会显示一堆^[[01;31m之类的乱码。-o加-E的组合是真正的“内容抽取”例如从日志里提取所有 IP 地址再统计出现次数这是排查来源 IP 是否集中时最快的路径。注意-c统计的是行数不是匹配次数一行里出现两次关键字也只计 1 行grep -o配合wc -l才能统计实际出现次数这个边界容易踩。# 统计包含 error 的行数 grep -c error app.log # 统计 error 实际出现的总次数 grep -o error app.log | wc -l4.2 sed 按行号与时间窗口切片sed在日志场景里最常见的两个用途是按行号切片和按时间范围切片。按行号切片适合在已知错误大约在文件中部、但不想grep大量噪声时使用。sed -n 1,100p表示只打印第 1 到第 100 行这个比head | tail组合少一次管道开销更低且不需要前置cat编号。# 打印第 100 到 120 行 sed -n 100,120p app.log # 删除前 100 行并输出剩余内容相当于跳过日志头部噪声 sed 1,100d app.log | head -n 50 # 全文替换 ERROR 为 WARN 并输出-i 落盘时慎用 sed s/ERROR/WARN/g app.log filtered.logd是删除模式1,100d表示把第 1 到第 100 行删除后输出剩余内容不修改原文件。s/old/new/g的g表示替换每一行里的所有匹配项如果没有g只替换每行的第一处匹配。落盘用 filtered.log重定向而不是-i直接改原文件因为日志文件通常是只读权限且改坏了不好恢复。时间范围切片用正则地址区间这是sed最硬核的用法# 打印 2023-11-09 18:00:00 到 18:01:00 之间的日志 sed -n /2023-11-09 18:00/,/2023-11-09 18:01/p app.log范围和范围的边界行都会被打印即“含头含尾”。前提是日志时间格式保持一致如果某行没有时间戳比如异常堆栈的后续行不会影响区间匹配因为sed是逐行扫描匹配起止模式。这个用法比grep 2023-11-09 18:0更精确后者会把 18:00 到 18:09 全搜出来。4.3 常见误用grep 管道前的 cat 是不是多余的cat app.log | grep error和grep error app.log结果完全一样但前者多了一次进程和一次管道读写。对几十 MB 小文件无所谓对几个 GB 的日志就是额外等几秒。我看到不少脚本里cat | grep的写法是从cat | grep | wc -l这种组合里带出来的习惯其实可以精简掉cat。真正需要cat的场景是多个文件合并再过滤cat a.log b.log | grep error或者需要编号后过滤cat -n app.log | grep error这时cat就不是多余的。5. 实战组合时间窗口、末次命中与实时统计5.1 按时间范围截取日志段最通用的做法是用sed的正则区间匹配但当天日志文件特别大时可以先用grep -n找到起止时间点的行号再交给sed按行号切片执行效率更高。假设要提取某天的 10:00:00 到 10:00:59 的日志# 第一步找到起止时间点的行号 START_LINE$(grep -n 2024-03-18 10:00:00 app.log | head -1 | cut -d: -f1) END_LINE$(grep -n 2024-03-18 10:01:00 app.log | head -1 | cut -d: -f1) # 第二步按行号切片并过滤异常关键字 sed -n ${START_LINE},${END_LINE}p app.log | grep -E ERROR|Exception -C 3 --colornever这里用head -1取第一个匹配到的行号时间在日志里按顺序递增的前提下第一个匹配就是期望边界。cut -d: -f1切出冒号前的行号部分。按行号切片避免了对整个文件做正则匹配的开销适合日志量在百万行以上时使用。5.2 取最后一次命中的上下文有时错误已经刷屏几百次看最后一次发生的堆栈才有价值。用grep -A取命中后的上下文再配合tail -n就能拿到最后一次# 显示最后一次 ERROR 出现的位置及它后面的 20 行 grep -n ERROR app.log -A 20 | tail -n 21 # 查看最后一次 ERROR 之前 5 行和之后 15 行 grep -n ERROR app.log -C 5 | tail -n 11grep -A 20会产生多段输出每段包含命中行和其后的 20 行。tail -n 21取最后 21 行正好对应最后一段命中行加 20 行上下文。-C 5 | tail -n 11则是最后一处命中前后各 5 行加上命中行本身共 11 行适合看崩溃点前后的状态。注意-A和-C同时使用后面的参数会覆盖两者不要混写。5.3 大日志实时追踪tail -F | grep --line-buffered实时追踪日志时直接tail -F app.log会看到全部输出噪声太大。加一层grep做关键字过滤但要加--line-buffered参数tail -F app.log | grep --line-buffered -E ERROR|OutOfMemory|Connection refused没有--line-buffered时grep出于性能考虑会做块缓冲即等到输出积累到一定量才刷出来导致明明日志在刷但你这边好几秒没动静。--line-buffered强制每匹配到一行就立即输出适合交互式实时监视。此场景下不要加-C上下文参数因为tail -F是持续流上下文行会跟着新日志不断刷新终端滚动速度反而加快。5.4 统计落点wc、grep -c 与场景选择统计日志量时wc -l最常用但它只统计“多少行”不是“多少字节”。查磁盘占用用ls -lh或du -h查行数用wc -l。grep -c统计匹配行数而grep -o | wc -l统计匹配次数二者在“一行里多次出现同一关键字”的场景下结果不一致。例如一行日志里打印了两次timeoutgrep -c timeout计 1grep -o timeout | wc -l计 2。判断故障影响面时用前者涉及行数评估错误频率时用后者实际次数这个区别在写自动化脚本时尤其重要。补充一点wc -l在处理不带末尾换行的文件时行数会比grep -c 少 1因为grep是按“换行符分隔的记录”计数而wc -l是统计换行符数量大日志尾部没有空行时这两个命令的结果差异容易被误判成丢日志。本文还有配套的精品资源点击获取
返回列表