简介Linux系统日志是诊断和调试问题的关键这份PDF专为运维人员、开发者和初入门的IT从业者整理日志查看与分析的常用命令。内容系统覆盖tail/head实时监控与按行定位cat/tac全文顺序及反向浏览less/more分页翻看与关键字搜索grep/sed正则过滤、上下文匹配和时间段截取并给出wc统计行数的用法。针对实际场景还梳理了排查错误关键字、定位指定时间窗口日志、查看关键字最后一次出现记录、统计关键字出现次数等典型操作例如tail -f持续监控、grep -C查看上下文、sed配合grep筛选区间日志等。资源为单文件PDF体积仅57KB保存和移动都很方便目前已有3140人学习下载。读者可快速建立从实时跟踪、分页查阅到正则提取、批量处理的日志分析思路遇到线上故障时更从容地定位根因。1. 查 log 日志先别急着 cat先定范围再选命令排查线上问题时最磨人的不是找不到日志而是日志文件太大、关键字太多、时间跨度太长一条cat下去终端直接卡死几百 MB 的文件把内存吃满。看 log 日志要学会的第一件事不是记命令而是先回答三个问题看哪一段、看哪些行、用什么工具打开。这份资源把 Linux 下查看日志的常用方法按tail/head、cat/tac、less/more、grep/sed分好类正好覆盖这个问题。适合后端开发、运维和 QA 同学尤其是那些经常要翻几个 GB 日志定位报错的人。先明确一点所有命令都遵循同一个原则能只读一部分就不要读全文能过滤就不要全量扫描。2. tail/head 与 cat/tac先定「看哪一段」再动手2.1 tail 的三种典型用法实时跟踪、取尾部、指定起始行日志文件的特点是新的内容永远追加在末尾所以查看最新日志时tail是出场率最高的命令没有之一。它的三种用法覆盖了日常排查的绝大多数场景。# 实时监控日志文件文件有新内容自动刷出 tail -f app.log # 实时监控同时限制只显示最后 10 行 tail -10f app.log # 查看文件末尾最后 100 行 tail -n 100 app.log # 从第 100 行开始显示直到文件末尾 tail -n 100 app.log第一行的-f是 follow 的意思终端会一直挂在那里日志一有新行就滚动输出我一般在排查接口报错时开两个窗口一个盯tail -f另一个用来触发请求。第二行-10f是简化写法等价于tail -n 10 -f作用不只是显示最后 10 行而是从倒数第 10 行开始跟踪适合日志刷得特别快、只想看最新一小段的时候用。第三行tail -n 100是最常用的查看尾部方式注意它等价于tail -n -100这个负号在不同发行版上行为有差异后面避坑章节会专门展开。第四行tail -n 100是很多新手容易搞混的点这里的100表示从第 100 行开始输出到文件结束不是「倒数第 100 行」。如果日志文件有 5000 行这条命令输出的是第 100 到第 5000 行约 4900 行内容。2.2 head 的边界显示头部与「去掉头部」两种语义head和tail恰好互补一个从文件头开始一个从文件尾开始。日常排查中它主要用来查看日志文件的起始部分比如应用启动时的初始化信息、框架加载的配置项这些内容通常只出现在文件开头。# 查看文本开头的前 100 行 head -n 100 app.log # 查看除了最后 100 行之外的全部内容 head -n -100 app.log # 查看第 1 到第 50 行 head -n 50 app.log第一行是最常规的读法配合tail -n 100可以快速了解一份日志的首尾各自发生了什么。第二行head -n -100的语义要特别留意它输出的是「去掉末尾 100 行后剩余的所有内容」等价于sed -n 1,$-100p的简化效果适合比较文件主体和尾部新增内容是否有差异。第三行没什么特别就是一个基础用法。实际工作和tail组合起来能解决一个很经典的问题我只想看第 100 到第 120 行怎么办单独用head或tail都做不到必须两个配合。# 先 cat 带行号取第 100 行之后的内容再取前 20 行 cat -n app.log | tail -n 100 | head -n 20这条管道命令的执行顺序是cat -n给全文件加上行号tail -n 100把第 100 行及之后的内容截出来最后head -n 20只保留这段内容的前 20 行最终得到的就是第 100 行到第 120 行。如果不要行号去掉-n参数即可。注意管道里tail -n 100的号不能丢丢掉就成了取末尾 100 行整个结果完全不对。2.3 cat 和 tac全文输出与倒序阅读的适用边界cat和tac适合处理小文件超过几十 MB 的日志文件不建议直接用它们全文加载这是血泪经验。cat输出全文tac从最后一行开始逐行逆序输出到第一行相当于把整个文件倒过来看。# 输出带行号的全文 cat -n app.log # 从尾部向头部倒序输出全部内容 tac app.logtac在什么场景下有用最典型的是查崩溃日志。很多应用在崩溃时会连续输出几十行的堆栈信息其中最关键的错误描述往往在最后几行。先tac把文件倒序grep一下关键字第一条命中的内容就是崩溃输出的尾部不用再翻几百行去找堆栈的起点。需要注意tac是整行反转不是把每个字符倒序输出所以日志时间戳从旧到新排列会变成从新到旧查看时心里要有数。2.4 组合命令的优先级管道顺序决定结果cat、head、tail组合时管道的书写顺序决定了整个处理链路的方向。常见错误是把head和tail的位置写反或者漏掉-n参数导致输出的行数和预期完全不一样。# 错误示范想取 100-120 行结果取到了最后 100 行的前 20 行 cat app.log | tail -n 100 | head -n 20 # 正确写法先按起始行截断再按数量取前 N 条 cat -n app.log | tail -n 100 | head -n 20我一般建议在调试这类组合命令时先用一个只有几百行的小测试文件跑一遍确认输出行数符合预期再上生产日志。小文件用wc -l数一下总行数心里先有个底能避免在几 GB 日志上跑完才发现参数写错了。3. less/more大日志不炸内存的翻页与定位3.1 为什么优先用 less 而不是 more大日志文件面前cat和more都靠不住。more只能向前翻页按b键往回翻在某些终端实现上并不可靠cat是一次性把全文读入终端日志一上 GB 直接卡死。less的优势在于它并不会把整个文件加载进内存而是按需读取当前屏幕需要显示的内容打开一个 2 GB 的日志文件内存占用可能只有几十 MB。# 直接打开日志文件进入翻页模式 less app.log # 设置退出时清除屏幕避免日志残留 less -X app.log # 打开文件的同时定位到第 100 行 less 100g app.log第二行的-X参数是我个人的偏好不加的话退出less时日志内容会留在终端上屏幕看起来全是残留文本不方便接着敲下一条命令。第三行的100g是「打开即定位到第 100 行」这里的g是 goto 的意思和进入交互界面后按100g跳转的效果一样。more也提一下它的价值在于极简环境里不一定装了less但more基本是标配。more -10 app.log可以设定每页展示 10 行适合看结构比较规整的配置类日志。除了这个参数more在交互能力和搜索能力上都明显弱于less所以只要环境允许我一般直接用less。3.2 打开即定位行号、关键字、百分比、字节位四个入口less最实用的能力不是翻页而是「打开文件的那一刻就落在你关心的位置」。大日志文件动辄几十万行打开后从第一行手动翻到目标位置不现实四个定位入口正好覆盖常见需求。# 定位到最后一行 less GG app.log # 定位到第 100 个字节的位置 less 100P app.log # 定位到 50% 的位置 less 100p app.log # 搜索关键字打开后直接定位到第一个匹配位置 less /Exception app.logGG跳到最后一行秒懂100P是跳到第 100 个字节适合跳过文件头部的固定前方信息100p跳转到 50% 位置注意这里的100p中的p是 percent表示百分比100 就是 100% 的位置实际使用时写50p才是中间。第四个/关键字是打开文件后立刻执行一次搜索直接定位到第一个匹配「Exception」的行这个在排查报错时比先打开文件再按/搜索少了一步操作。进入交互界面后常用的内部命令也别忘按/关键字向下搜索按?关键字向上搜索搜索后用n跳到下一个匹配用N跳到上一个匹配。翻页用CtrlF向后翻、CtrlB向前翻。退出直接按q。3.3 大文件打开后卡顿的排查方向如果less打开日志后翻页明显卡顿多半不是命令本身的问题而是文件的编码或格式有问题。二进制内容混入文本日志是一个常见原因less会对每个字节做解析遇到大量不可打印字符会拖慢渲染。解决办法是先退出用grep -I确认文件里是否包含二进制内容再决定是否要用strings清洗。另外日志文件如果是 Windows 行尾CRLFless的搜索和行号显示会略有偏差常见做法是先用dos2unix转换再打开或者用sed -i s/\r$//去掉回车符。这些细节不处理搜索关键字时会出现明明看到有「ERROR」却grep不到的诡异情况。4. grep/sed把日志切成你想要的那一片4.1 grep 的七个高频参数从匹配到上下文控制grep是日志排查的核心工具但多数人只用过grep 关键字 file这一种形式。真正能提高效率的是下面这几个参数组合它们分别解决「精确匹配」「只看匹配部分」「统计数量」「带行号输出」「保留上下文」这几类问题。# 全字匹配避免 ERROR 匹配到 ERROR_CODE grep -w ERROR app.log # 标记匹配颜色auto 表示输出到终端时着色 grep --colorauto Exception app.log # 只输出匹配到的内容而不是整行 grep -o -E [0-9]\.[0-9]\.[0-9]\.[0-9] app.log # 统计文件中包含匹配字符串的行数 grep -c timeout app.log # 输出匹配行及其上下各 2 行内容 grep -n -C 2 Exception app.log第一行-w是全字匹配只匹配完整的单词避免搜「ERROR」时把「ERROR_CODE」「ERROR_MSG」这种带后缀的也带出来在日志里这种字段噪声特别多。第二行--colorauto让关键字在终端里标红多文件日志刷屏时视觉定位快很多always 模式会把颜色转义符写进重定向文件所以重定向到文件时用--colornever更干净。第三行-o配合-E是提取 IP 的经典写法-o只输出匹配的子串而不是整行-E启用扩展正则。第四行的-c统计的是匹配行的数量不是匹配次数一行里出现两次「timeout」也只算一行这个区别后面统计章节会再强调。第五行-C 2是 context 的缩写输出匹配行及前后各两行排查异常时能直接看到报错发生前后发生了什么比单独看那一行有用得多。4.2 sed 按行号与时间范围切片的两种写法sed是流编辑器逐行读取、处理、输出。日志排查中它主要做两件事按行号切片和按时间范围切片。行号切片适合日志文件没有统一时间格式或者你想精确看某几行的场景。时间范围切片适合日志量巨大、只想看某几分钟内发生了什么的情况。# 只打印文件第一行 sed -n 1p app.log # 查看文件第 1 到第 10 行 sed -n 1,10p app.log # 删除第一行后输出不改原文件 sed 1d app.log # 把日志中的 IP 地址替换为脱敏文本 sed s/10\.0\.0\.[0-9]*/IP_HIDDEN/g app.log # 查看 22:43 到 22:44 之间的日志记录 sed -n /2025-03-18 22:43/,/2025-03-18 22:44/p app.log第一行的-n是关键它关闭了 sed 的默认输出配合p命令只打印匹配到的内容不加-n的话每一行都会被打印一遍输出会冗余一倍。第三行的1d是删除第一行后把剩余内容输出到屏幕原文件不会变想原地改要加-i参数但我不建议在日志文件上直接-i改坏了没法恢复。第五行是时间范围切片的写法两个/正则/之间用逗号连接p打印这个区间的内容。注意切片的截止条件是该正则第一次匹配到的时间戳如果 22:44 这一分钟内有多条日志从第一个 22:44 出现的位置开始就会停止输出这个边界问题要在结果里人工确认。4.3 组合场景一按时间窗过滤并保留上下文实际排查中单个命令很少能直接解决问题更多是grep和sed各出一招。比如先确认故障时间点然后用sed切出那段时间的日志窗口再对窗口内容做grep同时带上上下文。# 切出 14:00:00 到 14:05:00 的日志过滤 Exception 并保留前后 5 行 sed -n /2025-03-18 14:00:00/,/2025-03-18 14:05:00/p app.log | grep -n -C 5 Exception --colorauto这条管道的执行逻辑分成两段前段sed把整个文件的时间范围压缩到 5 分钟内的日志切片后段grep在这个切片里搜索关键字-C 5把匹配行前后的 5 行一起输出方便看异常发生时的完整上下文。-n给输出加上行号这里的行号是整个文件的行号不是切片内的相对行号后续想用sed -n 行号p回溯时可以直接用。4.4 组合场景二提取关键字前后内容与统计行数有时候不关心整行内容只想知道某关键字在日志里出现的频率以及最后一次出现时的上下文。这两个需求可以分别用-c统计和-A控制行数来实现。# 统计日志文件中包含 timeout 关键字的行数 grep -c timeout app.log # 等价写法管道到 wc -l grep timeout app.log | wc -l # 查看关键字最后一次出现时的上下文显示匹配行及后 10 行 grep timeout -A 10 app.log | tail -n 11 # 显示匹配行及前 10 行 grep timeout -B 10 app.log # 显示匹配行及前后各 10 行 grep timeout -C 10 app.log第一行grep -c统计的是包含关键字的行数第三行grep | wc -l先筛出所有匹配行再数换行符数量两者在文件末尾没有换行符时会差 1这个细节统计结果特别大时不太容易发现。第四行是「查看关键字最后一次出现」的经典组合grep -A 10先取所有匹配行及之后 10 行但输出会包含所有匹配位置所以外面再套tail -n 11取最后 11 行——也就是最后一次匹配的那一行加上它后面的 10 行。-B是向前的上下文-C是双向的实际使用中我更喜欢-C因为报错前后的日志往往一样重要。5. 避坑这些日志命令的翻车现场与排查方法5.1 tail -f 在日志轮转后失效现象用tail -f app.log实时跟踪日志一段时间后终端不再输出新内容但日志文件明明还在增长。原因日志文件被 logrotate 轮转旧文件被重命名为app.log.1新文件以app.log的名字创建。tail -f默认跟踪的是文件描述符不是文件名它还在读那个已经被重命名的旧文件自然看不到新内容。解决改用tail -F大写 F 会按照文件名重新打开文件轮转后自动切换跟踪新生成的文件。这条命令在跟踪应用日志时基本可以无脑代替tail -f。5.2 grep 把二进制文件当文本扫刷屏且拖慢现象grep ERROR *.log之后终端刷出大量乱码混杂着Binary file xxx.log matches的提示命令执行时间也比预期长很多。原因日志文件里混入了二进制内容可能来自应用异常写入的核心转储或编码错误的日志行。grep默认对二进制文件采取特殊处理输出匹配提示而不是具体内容但扫描过程仍然会完整读一遍文件在超大文件上会拖慢速度。解决用grep -I忽略二进制文件或者先用file app.log确认文件类型。对于确实混入二进制的日志常见做法是先grep -a以文本模式强制扫描配合-o只提取匹配片段避免整行乱码刷屏。5.3 less 100p 与 less 100g 的语义混淆现象有人想用less 100p app.log定位到第 100 行结果打开后停在了文件的 100% 位置也就是最后一行完全不是预期位置。原因100p中的p是 percent 的意思表示定位到文件的某个百分比位置100p就是 100%即文件末尾。定位到第 100 行应该用100gg是 goto。解决用less 100g app.log准确跳到第 100 行。记忆口诀是p对应百分比、g对应行号。同理GG之所以定位到最后一行是因为G在 vim 系操作习惯里代表文件末尾。5.4 head -n -100 在不同系统上行为不一致现象在 Linux 上执行head -n -100 app.log输出的是「去掉最后 100 行之后的所有内容」但在 macOS 或某些精简环境中执行同样的命令报错提示非法参数。原因head -n -100这种负数参数表示「排除末尾 N 行」的语义是 GNU coreutils 的扩展BSD 版本的head不支持这个语法。解决跨平台场景下改用兼容写法sed -n 1,$-100p或者grep -v配合行号处理。如果只是临时查看最稳的还是head -n 100这种标准参数负数参数的扩展功能只在确认系统支持时使用。5.5 wc -l 统计的是换行符最后一行会被漏掉现象用wc -l app.log统计日志行数和日志系统里显示的行数总差 1 行单独用tail -n 1又能看到内容。原因wc -l统计的是换行符的数量不是真正的行数。如果文件最后一行没有换行符wc -l不会把它计进去日志系统按行读取则会把最后一段内容也算一行。解决统计行数时用grep -c 或者awk END{print NR}更准确。统计关键字命中行数时同理grep -c是基于行的语义而grep | wc -l是基于换行符的语义最后一行没换行时两者差 1这个差异在大批量统计对比时会导致误判。6. 把日志查询做成日常习惯一套可复用的快速定位流程前面讲的是单个命令的用法和边界这一章把它们串成一个固定的排查流程。我的习惯是拿到一个线上问题先不要急着去翻日志先在终端执行一遍下面这个四步定位法把范围缩小到一行或几行再决定要不要用less进去细看。# 第一步确认故障时间窗口通常来自监控告警或用户反馈 # 用 sed 切出该时间段的日志输出到临时文件 sed -n /2025-03-18 14:00:00/,/2025-03-18 14:05:00/p app.log /tmp/error_window.log # 第二步在时间窗口内搜索关键字带行号和上下文 grep -n -C 5 Exception /tmp/error_window.log --colorauto # 第三步如果关键字太多按频率排序聚焦高发错误 grep -o -E ErrorCode: [0-9] /tmp/error_window.log | sort | uniq -c | sort -rn # 第四步针对最高频的错误码提取它在整个日志中的全部出现位置 grep -w ErrorCode: 503 app.log | wc -l第一步切时间窗口把分析对象从全量日志压缩到几分钟的小文件后续所有操作都基于这个临时文件速度大幅提升也避免在原始文件上反复全量扫描。第二步定位关键报错-C 5带出上下文这一步基本能确定问题的直接原因。第三步做频率统计-o -E提取结构化错误码sort | uniq -c | sort -rn按出现次数降序排列高频错误往往就是根因方向。第四步确认某个错误码的总量判断它是个别偶发还是大面积发生。这套流程里的每个命令都可以单独拆出来用在别的场景比如sort | uniq -c | sort -rn也适合统计日志中出现最多的 IP。时间窗口的边界是这套流程最大的坑sed的时间范围匹配是正则匹配时间戳格式稍微不一致比如日志里用2025-03-18T14:00:00而不是2025-03-18 14:00:00匹配直接失效。我一般会先用grep 2025-03-18 14:00 app.log | head -1验证一下时间戳格式再跑sed切片这样能避免切出空文件还以为是日志没写。从那以后我每次接到日志排查任务都强制自己先跑一遍这个四步流程哪怕问题可能很简单也会先用它把范围框住再决定是否深入。这套方法帮我避开了很多次直接在几个 GB 的日志里盲目grep的尴尬也减少了对日志分析平台的依赖。希望这套流程能帮你更快地定位问题把时间花在修复上而不是翻日志上。本文还有配套的精品资源点击获取