尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

深入理解grep:从基础用法到日志排查实战

发布时间:2026/9/7 15:25:06

资讯中心
01
ARTICLE

深入理解grep:从基础用法到日志排查实战

深入理解grep:从基础用法到日志排查实战
“每天一个Linux命令”系列grep这可能是你最常用的排查工具老规矩今天这个系列轮到 grep。我最早接触 Linux 的时候其实不太理解为什么大家天天把 grep 挂在嘴边。直到有次线上服务出问题我需要在几万行日志里定位一条报错在几十个进程里确认某个服务是否还活着在配置文件堆里搜某个参数到底写在哪才发现这玩意几乎是所有排查动作的地基。后来我带新人第一个星期只让他们练三件事grep、管道、vim 看文件。这三件事熟练了Linux 日常操作基本不会卡壳。这篇不打算把 man 手册抄一遍而是按照我自己的使用习惯把 grep 真正高频的用法、组合方式、以及踩过的坑整理出来。无论你是刚入行的运维、写代码的开发、还是准备面试的学生这都应该能成为你顺手就能翻的参考。如果你已经用了很久 grep重点可以看最后两章——自匹配的坑和几个容易被忽略的细节我自己在这上面吃过不少亏。1. grep 命令定位它不是“搜索文件”而是“按模式过滤文本”1.1 从名字理解 grep 的底层逻辑grep 这个名字看着奇怪其实是一个古老缩写g/re/p也就是 global regular expression print全局正则表达式打印。这个名字基本把它做的事情说透了读取输入逐行去匹配正则表达式匹配上的行就打印出来匹配不上的就丢掉。理解“逐行处理”这一点很关键。grep 不是把整个文件一次性读进内存再去翻而是一行一行地读处理完一行就输出一行。这也是为什么 grep 能轻松处理几个 GB 的大日志文件而不至于把内存打满因为它的工作方式决定了内存占用基本是固定的。你可以把它想象成流水线上的安检员每一行文本就是一个人只有符合规则的才放过去其他的直接走旁路。单看文件名可能会以为它只能搜“文件内容”但实际它的输入源有三种直接给定文件名、从标准输入读取、和其他命令用管道拼接。第三种才是它在 Linux 世界里威力最大的用法后面会专门讲。1.2 五个出现频率最高的参数先记这五个就够了grep 的参数很多但日常最常用的基本就是下面这几个我按使用频率排序-i忽略大小写。查错误日志时Error、ERROR、error 都有可能出现不加这个参数很容易漏。-v反向匹配也就是“不含某个关键词的行”相当于排除。-n显示行号查配置、查代码时几乎必用定位全靠它。-c统计匹配行数而不是输出内容本身。想看某个关键字在文件里出现了多少行用它。-w按单词匹配避免“user”把“username”“user_id”也带出来。举个例子排查 Nginx 配置里所有不含注释的行grep -v # /etc/nginx/nginx.conf再比如统计一个日志文件里出现过多少次 Timeoutgrep -c Timeout app.log-c统计的是“行数”而不是“次数”。同一行里 Timeout 出现三次-c也只会计数一次。如果你确实要统计“出现次数”那得用grep -o Timeout app.log | wc -l-o可以把每个匹配内容单独打一行再用wc -l数行数。这个组合在统计 IP 访问次数时特别管用。1.3 上手实例5 分钟把它用起来先别急着啃正则基础搜索就直接上。假设我要在今天所有的日志文件里找一条包含“OutOfMemoryError”的记录grep -n OutOfMemoryError /var/log/app/2024-06-18.log如果当天文件被分割成多个还可以用通配符指定目录下的一批文件grep -n OutOfMemoryError /var/log/app/2024-06-18*.log这一步的输出会自动带上文件名前缀比如/var/log/app/2024-06-18-10.log:42:xxx方便你一眼看出结果落在哪个文件、哪一行。到了这一步grep 的第一层用法你已经会了接下来要进阶的是正则和组合。2. 正则表达式从“按词找”到“按规律找”2.1 基础正则与扩展正则为什么要区分grep 默认使用的是基础正则表达式BRE而egrep或者grep -E使用的是扩展正则表达式ERE。两者的区别不在于谁更“高级”而在于一些元字符需不需要转义。在基础正则里、?、|、{}、()这些字符默认是字面量想让它表达“一个或多个”“可选”“或者”“分组”这些含义必须加上反斜杠。比如a\表示一个或多个 a。在扩展正则里这些符号直接就能用不需要加反斜杠写起来自然更舒服。所以我个人的习惯是只要涉及正则一律用grep -E省得纠结转义。很多人可能觉得默认的 grep 就够了但如果哪天看到一个命令里写着\{2,\}这种写法不要觉得奇怪那就是基础正则下的次数匹配。2.2 高频正则在真实场景里的写法日常最常碰到的正则需求其实很固定我把常用的列出来每个配一个小例子需求正则写法示例说明行首匹配^grep ^# config.conf找出所有注释行行尾匹配$grep error$ app.log找以 error 结尾的行任意单字符.grep a.c file可以匹配 abc、adc、a1c字符集合[abc]、[0-9]、[a-z]grep [0-9]\{4\} a.log或grep -E [0-9]{4} a.log匹配四位数字一个或多个扩展正则grep -E abc file匹配 abc、abbc零个或多个*grep ab*c file匹配 ac、abc、abbc零个或一个?grep -E ab?c file匹配 ac、abc或逻辑|BRE/ ERE分组\(\)BRE/()EREgrep -E (error举个我真实用过的场景。有次排查日志里的异常耗时要找出所有耗时超过 3000 毫秒的请求日志格式类似cost1234ms。用扩展正则写grep -E cost[3-9][0-9]{3,}ms access.log这个表达式的意思很直白[3-9]是千位从 3 到 9[0-9]{3,}是后面至少跟着三位数这样 3000 以上的都会被捞出来。你可能会问 3000 本身呢[3-9][0-9]{3,}对 3000 能匹配上因为千位是 3后面三位 000。如果我还想包含 2000 到 2999就得再加一类规则不过实际排查中很少需要一次把边界算得那么严大范围命中后人工再确认也不迟。2.3 关于引号一个很多新手忽略的坑grep 的模式建议一律用单引号包起来。原因是单引号能让 shell 不对内容做任何展开里面写什么就是什么。双引号则不同如果模式里有$、反引号、反斜杠shell 可能会先解释一遍再传给 grep。比如你想在日志里搜一个包含$字符的变量名grep $PATH env.log如果你用了双引号grep $PATH env.logshell 会先把$PATH展开成环境变量的值那搜的东西就完全不对了。这个坑很隐蔽因为查别的文字时双引号和单引号结果都一样一旦遇到特殊字符就会莫名其妙地搜不到。顺带一提如果你搜的是中文内容在个别老系统上可能出现乱码或搜不到可以试试先export LC_ALLC.UTF-8或export LANGen_US.UTF-8再执行 grep。这个问题在纯英文环境的服务器上很少暴露但一旦遇到多半就是 locale 设置的事。3. 进程管理组合拳ps 管道 grep 和 kill 的完整链路3.1 热词里的“ps -ef | grep java”到底能查出什么几乎所有 Linux 相关的搜索热词里都有ps -ef | grep java它几乎是运维排查进程的默认起手式。先看ps -ef会输出什么UID PID PPID C STIME TTY TIME CMD root 1 0 0 Jun10 ? 00:00:08 /sbin/init root 1234 1 0 Jun10 ? 00:00:00 /usr/sbin/sshd -D appuser 5678 1 99 10:30 ? 00:02:31 java -Xmx2g -jar app.jar列的含义分别是用户、进程 ID、父进程 ID、CPU 占用率、启动时间、终端、累计 CPU 时间、完整命令。很多人说“用ps -ef | grep java查看启动时间”其实STIME列显示的只是启动的日期或时刻默认精度不够高。如果你真想看精确到秒的启动时间更好的方式是用ps -eo pid,lstart,cmd | grep javalstart会显示完整的启动时间比如Thu Jun 18 10:30:21 2024。所以正确的用法组合是ps -eo pid,lstart,cmd | grep java这里我不建议用ps -ef | grep java去查启动时间因为看到的是简化后的时间。先记住这个差异后面排查进程卡的时长时能少绕路。3.2 为什么每次 grep 都会多出一个“自己”用过ps -ef | grep xxx的人应该都见过这种输出root 10086 1 0 10:30 ? 00:00:00 java -jar app.jar root 10112 1 0 10:31 ? 00:00:00 grep --colorauto java第二条明显不是我们要找的进程它是 grep 命令自己的进程。原因其实很简单管道执行时系统会同时启动ps和grep这两个进程然后 grep 在扫描 ps 的输出时输入里包含了它自己的命令行信息因为ps -ef会列出所有进程包括正在运行的 grep 命令本身于是把自己也匹配上了。解决方式有几种最经典的是用字符类ps -ef | grep [j]ava[j]ava能匹配 java但 grep 自己的命令行里写的是[j]ava它不会匹配文本形式的[j]ava只有真正的 java 进程会被列出来。这个小技巧在面试里偶尔会被问到实际用起来也确实干净。另一个更直接的方式是pgrep -f java它是专门为查进程设计的命令天然规避了自匹配问题。但 pgrep 默认只输出 PID想看完整命令还是要ps -fp $(pgrep -f java)或者直接pgrep -af java。两种方式我都用看当时要做什么。3.3 从查询、过滤到 kill 的完整实操搜热词里有一条很典型的操作用ps -e | grep apt列出所有带 apt 字样的进程然后用 kill 命令一一杀死。这个流程本质就是三件套# 第一步找到目标进程 ps -ef | grep [a]pt # 第二步提取出 PID 列 ps -ef | grep [a]pt | awk {print $2} # 第三步把 PID 传给 kill ps -ef | grep [a]pt | awk {print $2} | xargs kill如果确定要大开杀戒最后那个 kill 可以换成kill -9但我个人强烈建议不要一上来就用-9。kill默认发送的是SIGTERM相当于客气地请进程自己收拾东西离开Java 进程能有机会执行关闭钩子、释放端口而kill -9是SIGKILL直接把进程砍了资源不清理文件可能写到一半甚至留下一些孤儿进程和脏数据。我用一个真实事故说明。那时候我图省事对一批批量任务进程执行了kill -9结果其中一个进程正在写一个中间结果文件内容是写到一半的半个 JSON。下游任务读这个文件直接解析失败连锁报了十几个告警。从那以后我的习惯是先kill等三秒看进程还在不在再用kill -9。能用kill解决的绝不上来就-9。还有一个非常容易被忽略的问题用xargs kill之前务必先看一遍 PID 列表确认没有当前正在跑的、不想杀的关键进程。尤其是那种过滤条件比较宽的命令比如grep apt很可能连系统里的aptd守护进程也匹配进去了杀错以后要花更长时间去恢复。4. 日志排查与代码搜索的高级打开方式4.1 递归搜索整个目录怎么搜才不“爆炸”grep -r可以递归搜索目录下所有文件比如在项目代码里找一个函数在哪定义grep -rn getUserInfo src/-r是递归-n是显示行号。这样一条命令就能把整个代码库里所有相关位置列出来。但问题来了如果目录里有node_modules、.git、vendor、build这些巨型目录grep 会一股脑全扫进去又慢又杂。正确的姿势是用--exclude-dir把无关目录排掉grep -rn --exclude-dirnode_modules --exclude-dir.git getUserInfo src/如果只想搜特定类型的文件用--include限制grep -rn --include*.java getUserInfo src/只看文件名、不要内容可以用-l只统计文件数量用-l | wc -l。在特别大的代码仓库里--include和--exclude-dir配合基本是标配不然很容易扫出一个文件叫*.min.js全是压缩代码结果挤满屏幕真正的命中反而被淹没。4.2 查日志时带上上下文-A、-B、-C很多时候光搜出一个“ERROR”根本不够你得知道这行错误前面发生了什么、后面跟了什么。grep 提供了三个参数-B 3显示匹配行的前 3 行Before-A 3显示匹配行的后 3 行After-C 3显示匹配行前后的各 3 行Context日常排查日志我基本只用-C一次把上下文都带上grep -n -C 5 NullPointerException app.log如果错误日志量很大还可以配合tail -f做实时过滤看线上新产生的报错tail -f app.log | grep --line-buffered -E ERROR|Exception--line-buffered很关键。不加它时grep 会先攒一段输出再打印你在终端上看到的错误会有明显延迟加上它之后grep 每匹配一行就立刻输出实时性完全不一样。这也是我踩过坑才记住的细节一开始还以为 tail -f 失灵了。4.3 另一个准确率更高的搜索思路先 find 再 grep在大目录里搜内容直接grep -r是最省事的但未必是最快的。如果你知道要找的文件大概在哪里或者想按文件名字先圈定范围可以先用 find 找到具体文件再交给 grep。比如在 /opt 下所有.conf文件里搜端口配置find /opt -name *.conf -type f -exec grep -Hn listen {} \;find 和 grep 搭配的好处是可控性更强。你可以先看 find 找出了哪些文件确认范围没问题再批量 greek避免 grep -r 扫到一堆不想看的文件。也可以借助 xargs 把文件列表传给 grepfind /opt -name *.yml -type f | xargs grep -n password不过文件路径里如果带空格直接| xargs grep可能会出错更稳妥的是xargs -d \n grep -n。个人经验是路径里有空格的情况虽然不常见但一旦出现xargs报错很难一眼看出来提前写上-d \n能省很多事。这也算是被坑过的经验了。5. 常见问题、避坑经验与排查速查表5.1 我踩过的几个坑提前帮你避开第一个坑是自匹配前面已经讲过了解决方式就是[j]ava或pgrep。第二个坑是 grep 搜出来的二进制文件终端会提示Binary file xxx matches但不显示具体内容。如果日志里混入了二进制内容可以用grep -a强制把二进制当作文本处理我处理 Java 进程 dump 出来的堆转储时经常用。第三个坑是编码问题。有次我在日志里搜中文关键字明明在 vim 里能看到用 grep 就是搜不到。后来查了一下是文件编码是 GBK而终端和 grep 用的 locale 是 UTF-8。解决办法是先把文件转码再搜或者用iconv -f GBK -t UTF-8 file.log | grep 关键字。老系统上这问题出现频率不算低遇到怪事时先别怀疑 grep 坏了先看看文件编码。第四个坑是grep慢。大文件加复杂正则时确实会慢尤其正则写得不合适的时候。比如grep -E .*error.*这种开头的.*会让正则引擎做大量回溯性能很差。能缩小范围就缩小用^.*error不如直接error很多时候 grep 默认就是逐行包含匹配不需要额外写.*。真遇到超大文件还可以用LC_ALLC grep提升速度因为 C locale 下排序和匹配规则简化了。实测大文件上能快不少。5.2 常见问题速查表现象常见原因解决方式搜不到但 vim 里能看到文件编码与 locale 不一致先 iconv 转码或调整 LANG结果里总是多一个 grep 进程grep 自匹配用[j]ava或pgrep -f提示 Binary file matches匹配到了二进制文件加-a强制文本模式匹配行太多终端卡住没有限制输出量追加 大文件搜索慢正则回溯或 locale 影响简化正则加LC_ALLC$、*等符号搜不出来shell 先展开了变量或通配符用单引号包裹模式tail -f配 grep 有延迟管道缓冲加--line-buffered忘了排除目录搜出一堆 node_modules没有用--exclude-dir加排除项后重搜这里我再补一个细节。grep默认匹配的是包含关系也就是“这一行里包含某个模式就算命中”。如果你想精确匹配整行要加-x或者用^模式$来锚定。比如查进程时ps -ef | grep -x ...基本用不上但处理配置文件时如果只想找某个 key 单独占一行的情况-x就很有用了。5.3 grep 在整个命令体系里的位置顺便聊聊面试高频考点说了这么多最后把 grep 放到整个 Linux 命令体系里看一眼。以日志分析为例经典的组合是grep sed awkgrep 负责按模式捞行sed 负责批量替换和按行提取awk 负责按列做统计。这三者配合基本能解决 80% 的日常文本处理需求。比如统计某个接口的平均响应时间可以用grep GET /api/user access.log | awk {print $NF} | awk {sum$1;count} END {print sum/count}很多公司的运维和后端面试题都会围绕这个组合展开比如“统计日志中每个 IP 出现的次数”“找出耗时最长的请求”等等。核心考点就是考察你能不能把 grep 的筛选、awk 的分列、sort/uniq 的统计组合起来。建议平时多拿手头的日志练手练熟了面试时基本不用背题。最后分享一个小技巧给 grep 加上颜色和行号的习惯如果让我总结一个最值得长期坚持的习惯那就是让 grep 默认带颜色。虽然很多发行版默认就会alias grepgrep --colorauto但如果你发现自己的 grep 输出里没有高亮可以在~/.bashrc里加上alias grepgrep --colorauto颜色高亮的好处不是好看而是在一大屏输出里命中位置一眼就能扫出来。尤其配合-n显示行号排查效率能提升一个档次。到现在为止grep 的基础用法、正则进阶、进程组合、日志排查、避坑经验都过了一遍。你如果只记住一件事那就记住先过滤再处理。grep 永远是管道的第一道关卡也是你面对一堆未知信息时最应该先拿出来的工具。下次再遇到“查进程、查日志、查配置”的需求希望你能直接想到该用哪条命令。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。