首页 > 编程知识 正文

tailgrep多次,tail命令搜索字段

时间:2023-05-03 23:15:35 阅读:19374 作者:3272

对于开发者和运输商来说,如果系统发生故障,第一步就是查看日志。 查看日志时经常遇到的一个需求是通过关键字进行搜索,日常开发人员的IDE集成了强大的搜索功能,但由于系统通常部署在Linux系统上,因此通常只有命令行界面。 在此基础上该怎么搜索? 恐怕有些同学没那么清楚。

也有人通过ftp等下载日志进行本地搜索。 如果是标致的小猫点的文件还可以,但是日志文件往往很大,这样的方法无疑效率很低。

这里介绍一种比较快速的方法。 也不需要特别的高级命令。 只需将tail和grep两个命令组合起来,即可达到这种效果:

可以用关键字搜索; 也可以在显示包含关键字的行时突出显示关键字。 也可以一起显示有关键字的行的上下文,例如上下10行的内容。 效果示意图:如下所示

在这里,我使用云主机的nginx访问日志树立了榜样。 我搜索了某篇文章的url的关键字“a-port”,显示了搜索结果和上下文。 关键字显示为红色,上下文也显示,可见多个搜索结果之间用蓝色的短横分隔。

具体说明实现这种检索的方法。 首先,我们将具体介绍每个命令和参数,然后介绍如何结合。 最后还给出了脚本化的高级用法。

tail命令

首先是tail命令。 因为要查看日志通常从后面的最新日志开始查看,所以tail命令是从后向前查找。

例如,以下命令显示access.log最后10行的内容:

tailaccess.log

tail指定行数

默认情况下,tail只显示最后10行。 一个日志较多的APP应用程序可能不够。 为此,需要搜索更多的行。

如果想实时查看日志,请参考以前的这篇文章,使用tail -f实时观察服务器日志的输出

tail可以与-n参数结合使用来指定行数。 例如,以下命令显示最后30行日志:

tail-n 30 access.log

注意如果不太记得:参数,也可以使用完整的-n命令参数lines : tail---- lines 30 access.log

grep命令

tail只能打印显示日志。 在很多情况下,这是不够的。 日志通常非常多,很多没有用。 我们还需要过滤和筛选日志的内容。 在这种情况下,可以使用grep命令。

grep命令的基本使用方法如下。 如果您有一个名为index.html的文件,并且想要在其中搜索关键字official,可以像这样使用:

grepofficial index.html

结果是以下:

显示包含关键字的行,并突出显示关键字。

对于突出显示问题,如果缺省情况下未突出显示,则可以自己添加--color选项。 这样: grep-- colorofficialindex.html

通常,不要使用grep命令直接搜索整个日志文件。 因为日志文件通常很大,grep也从开头开始搜索,所以可能会搜索到很多不感兴趣的历史记录。

稍后将介绍如何通过组合tail和grep命令来缩小搜索范围。

有空格的关键字

如果关键字包含多个单词且有空格,则可以用“”单引号括起来。 例如,

grep'english version' index.html

正则表达式显示上下文

有时候,我们不仅想找到关键孩子所在的行,还想显示所在行上下的几行。

这在查找异常信息时非常常见。 另一方面,异常堆栈打印在非常多的行上。 另外,我们通常需要前后看看发生了什么。

在这种情况下,可以使用grep的-NUM参数实现以下:

grep-5 official index.html

或使用-C

grep-C 5 official index.html

这表明,official关键字不仅会找到某一行,还会显示某一行前后的五行。

后面的数字5表示前后5行,-10则表示前后10行

结果是以下:

正则表达式显示行号

为了更清楚地显示,也可以显示行号。 使用-n参数,如下所示

grep-5 -n official index.html

结果如下图:

可以看到,official关键字为21行,行首的行号特别用冒号' : '表示; 另外,关键行的前五行(16~20 )和最后五行)也显示在一起。

如果我们跟踪异常,这些上下文中的信息可能会有很多帮助。

使用管道符号

p>

现在已经介绍完了 tail 和 grep 命令, 但还有一个问题, 如果直接在日志文件中去 grep 的话, 因为文件通常特别大, 而且很多历史数据可能不是我们想要的, 因此最好的方式是先用 tail 得到后面的那些行, 然后把 tail 出来的结果再交给 grep 命令去过滤, 而管道符可以实现这个目的, 管道符在命令行中就是一个"竖杠": |.

它可以把两个命令结合起来, 把请一个命令的输出当作后一个命令的输入.

用管道符 | 结合 tail 和 grep 命令

用管道符结合 tail 和 grep 命令可以这样去写:

tailerror.log | grep stream

注意: grep 之前的竖杠 |.

上述命令会把 tail 出来的最后 10 行的内容交给 grep 去搜索过滤, 并找出其中含有 stream 关键字的行, 结果如下:

结合前面所讲, 如果想在更大范围搜索并显示关键字的上下文, 最终可以这样去写:

tail-n20error.log|grep-3stream

以上命令在最后 20 行中去搜索 stream 关键字并显示关键字所在行及上下各 3 行的内容, 结果如下:

高级用法

有了以上命令, 要搜索异常信息就简单了不少, 而且更容易观察, 不过还是有一个问题, 就是整个命令还是太长了些, 如果想进一步简化, 则可以考虑将整个命令做成一个脚本, 并将部分参数值参数化, 这就带有一定的编程的味道了, 好在这对于我们程序员来说, 不算太难的事, 甚至是我们的日常, 下面说说怎么去实现.

先说下效果, 我们会编写一个脚本叫 search.sh

当然这个名字你可以自己去取

然后这样去用:

./search.shstream203

然后其效果就像执行下述命令一样:

tail-n20error.log|grep-3stream

如果不打算传入行数及上下文的数目, 而使用脚本中定义的缺省值, 整个命令还可以简化成:

./search.sh stream

仅需要传入要搜索的关键字即可, 其它参数保持缺省.

自定义命令

就以搜索我本机上的 nginx 的 error.log 为例吧, 首先创建一个脚本文件 search.sh

touchsearch.sh

文件的内容如下:

#!/pgyb/bashcd /usr/local/nginx/logstail -n 20 error.log | grep --color -3 stream

注意: 放入脚本文件时, 如果没有高亮, 需要自行加上 --color 选项

逻辑也比较简单, 就是先进入 error.log 所在文件夹, 然后执行查找.

有了 cd 命令, 就可以直接把脚本放在远程登录后的用户目录下, 比如 /root 下, 这样进去了就可以直接执行, 连进入文件夹的动作也省略了.

另外, 如果不想用 cd 命令, 也可以在 tail 中写上完整路径名.

当然, 现在脚本还是比较死的, 搜索的关键字被写死了. 不过目前来说, 我们先测试其它方面, 先把文件改成可执行的:

chmod755 search.sh

然后可以先执行一遍看看是否 ok, 如果 ok 了, 再下一步准备把关键字参数化.

./search.sh

参数传递

现在需要把搜索的关键字给参数化, 不然执行脚本时, 始终只能搜索 'stream' 这个关键字, 这显然不是我们希望的.

如果是用我们熟悉的语言, 比如 java, javascript, 写一个可以接收参数的函数是很简单的, 其实对于 bash 这种脚本语言来说, 主要的问题是我们不熟悉其语法, 这个只要稍微查下它的手册或是在网上搜索下即不难知道.

过程就不提了, 具体而言是这样的:

#!/pgyb/bashcd /usr/local/nginx/logstail -n 20 error.log | grep --color -3 $1

就是把 stream 这个写死的关键字变成一个变量 $1, 自然 $ 符号就是 bash 跟定义变量有关的.

自然, 你应该能猜到, 如果想传递更多的参数, 就用 $2, $3, 以此类推.

然后你这样

./search.sh hello

那么脚本文件名后面跟的字符串'hello'就会传递给 $1 这个变量, 于是就相当于执行了:

tail -n 20error.log | grep --color -3 hello

同理, 可以把 tail 的行数和 grep 的上下文的行数也参数化:

#!/pgyb/bashcd /usr/local/nginx/logstail -n $2 error.log | grep --color -$3$1

如此一来, 当执行下述命令时:

./search.shhello100010

就相当于:

tail -n 1000error.log | grep --color -10 hello

也即在日志文件的最后 1000 行里搜索, 并显示关键行上下各 10 行的内容.

缺省值及判断逻辑

自然, 很多时候可能只想传递关键字即可, 当把 tail 的行数和 grep 的上下文的行数也参数化后, 每次调用也要传递它们是不方便的, 当如果把它们写死的话, 有时我们可能又需要适当变化, 这个矛盾怎么解决呢? 答案是利用缺省值和逻辑判断.

如果是常用的语言, 如 java, javascript, 写个这种判断相信对你来说是个再简单不过的事, 对于 bash 这种脚本语言, 最大的问题还是我们不熟悉其语法, 那么这个还是跟之前说的那样, 查查手册, 或搜索下, 过程就省略了, 具体来说, 可以这样:

简单说就是定义两个变量lineCount和contextCount, 分别具有 1000 和 10 两个缺省值, 然后利用 if 判断用户是否输入了第二和第三个参数, 如果有, 就用它们的值取代缺省值, 没有的话就使用缺省值, 这样一来就比较灵活了.

如果只输入了关键字:

./search.sh hi

结果就是这样:

tail -n 1000error.log | grep --color -10 hi

输入两个参数:

./search.shhello300

结果就是这样:

tail -n 300error.log | grep --color -10 hello

输入三个参数:

./search.shhey5008

结果就是这样:

tail -n 500error.log | grep --color -8 hey

当然还是有个问题, 笨笨的篮球想只调整第三个参数时, 你还是必须得传入第二个参数, 否则传入的值只会被第二个参数优先获得.

命令输出

最后, 如果你想在执行前回显一下将要执行的命令, 还可以利用 echo 这个命令来实现, 它同样支持变量:

这样一来, 执行前就会先打印出将要执行的命令.

总结

综上所述, 从单个命令到复合命令, 再到脚本化和参数化, 其实是用了编程中的抽象这一手法, 这是我们解决重复性以及解决复杂性的一种重要手段.

当一个命令或几个的复合命令比较繁琐时, 我们就用一个脚本文件去做抽象, 保留不变的东西, 把变化的东西参数化, 外部化, 通过这样的方式, 就简化了执行(调用)的过程, 减少了重复.

毕竟, 如果你经常需要查找日志的话, 输入简单的./search.sh foo比反复输入如此之长的一串tail -n 1000 error.log | grep --color -10 foo要方便快捷的多.

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。