精华内容
下载资源
问答
  • linux通过grep根据关键字查找日志文件上下文 1、在标准unix/linux下的grep命令中,通过以下参数控制上下文的显示: grep -C 10 keyword catalina.out 显示file文件中匹配keyword字串那行以及上下10行 grep -B 10 ...

    linux通过grep根据关键字查找日志文件上下文

    1、在标准unix/linux下的grep命令中,通过以下参数控制上下文的显示:

    grep -C 10 keyword catalina.out 显示file文件中匹配keyword字串那行以及上下10行

    grep -B 10 keyword catalina.out 显示keyword及前10行

    grep -A 10 keyword catalina.out 显示keyword及后10行

    2、查找的结果比较大时,为了方便定位问题,也可以重定向到文件中,比如:

    grep -C 10 keyword catalina.out > aaa.txt

    3、统计包含某个关键字的个数

    grep -o keyword catalina.out | wc -l

    4、如果一行最多一个关键字,可以简写为:
    grep -c keyword catalina.out

    5、查看grep版本的方法是

    grep -V

    Grep命令详细说明:

    Usage: grep [OPTION]… PATTERN [FILE]…
    Search for PATTERN in each FILE or standard input.
    PATTERN is, by default, a basic regular expression (BRE).
    Example: grep -i ‘hello world’ menu.h main.c

    Regexp selection and interpretation:
    -E, --extended-regexp PATTERN is an extended regular expression (ERE)
    -F, --fixed-strings PATTERN is a set of newline-separated fixed strings
    -G, --basic-regexp PATTERN is a basic regular expression (BRE)
    -P, --perl-regexp PATTERN is a Perl regular expression
    -e, --regexp=PATTERN use PATTERN for matching
    -f, --file=FILE obtain PATTERN from FILE
    -i, --ignore-case ignore case distinctions
    -w, --word-regexp force PATTERN to match only whole words
    -x, --line-regexp force PATTERN to match only whole lines
    -z, --null-data a data line ends in 0 byte, not newline

    Miscellaneous:
    -s, --no-messages suppress error messages
    -v, --invert-match select non-matching lines
    -V, --version display version information and exit
    –help display this help text and exit

    Output control:
    -m, --max-count=NUM stop after NUM matches
    -b, --byte-offset print the byte offset with output lines
    -n, --line-number print line number with output lines
    –line-buffered flush output on every line
    -H, --with-filename print the file name for each match
    -h, --no-filename suppress the file name prefix on output
    –label=LABEL use LABEL as the standard input file name prefix
    -o, --only-matching show only the part of a line matching PATTERN
    -q, --quiet, --silent suppress all normal output
    –binary-files=TYPE assume that binary files are TYPE;
    TYPE is ‘binary’, ‘text’, or ‘without-match’
    -a, --text equivalent to --binary-files=text
    -I equivalent to --binary-files=without-match
    -d, --directories=ACTION how to handle directories;
    ACTION is ‘read’, ‘recurse’, or ‘skip’
    -D, --devices=ACTION how to handle devices, FIFOs and sockets;
    ACTION is ‘read’ or ‘skip’
    -r, --recursive like --directories=recurse
    -R, --dereference-recursive
    likewise, but follow all symlinks
    –include=FILE_PATTERN
    search only files that match FILE_PATTERN
    –exclude=FILE_PATTERN
    skip files and directories matching FILE_PATTERN
    –exclude-from=FILE skip files matching any file pattern from FILE
    –exclude-dir=PATTERN directories that match PATTERN will be skipped.
    -L, --files-without-match print only names of FILEs containing no match
    -l, --files-with-matches print only names of FILEs containing matches
    -c, --count print only a count of matching lines per FILE
    -T, --initial-tab make tabs line up (if needed)
    -Z, --null print 0 byte after FILE name

    Context control:
    -B, --before-context=NUM print NUM lines of leading context
    -A, --after-context=NUM print NUM lines of trailing context
    -C, --context=NUM print NUM lines of output context
    -NUM same as --context=NUM
    –group-separator=SEP use SEP as a group separator
    –no-group-separator use empty string as a group separator
    –color[=WHEN],
    –colour[=WHEN] use markers to highlight the matching strings;
    WHEN is ‘always’, ‘never’, or ‘auto’
    -U, --binary do not strip CR characters at EOL (MSDOS/Windows)
    -u, --unix-byte-offsets report offsets as if CRs were not there
    (MSDOS/Windows)

    ‘egrep’ means ‘grep -E’. ‘fgrep’ means ‘grep -F’.
    Direct invocation as either ‘egrep’ or ‘fgrep’ is deprecated.
    When FILE is -, read standard input. With no FILE, read . if a command-line
    -r is given, - otherwise. If fewer than two FILEs are given, assume -h.
    Exit status is 0 if any line is selected, 1 otherwise;
    if any error occurs and -q is not given, the exit status is 2.

    Report bugs to: bug-grep@gnu.org
    GNU Grep home page: http://www.gnu.org/software/grep/
    General help using GNU software: http://www.gnu.org/gethelp/

    展开全文
  • 大咖揭秘Java人都栽在了哪?...>> 对于一个开发或运维人员而言, 当系统出现故障时, 第一步常常就是查看... 查看日志经常碰到的一个需求就是按关键字去搜索, 在日常开发机子的 IDE , 都集成了强大的搜索功能...
    此文转载自:https://my.oschina.net/goldenshaw/blog/4703734

    对于一个开发或运维人员而言, 当系统出现故障时, 第一步常常就是查看日志. 查看日志经常碰到的一个需求就是按关键字去搜索, 在日常开发机子上的 IDE 上, 都集成了强大的搜索功能, 但因为系统通常部署在 Linux 系统上, 一般只有命令行界面, 在其上应该怎么去搜索呢? 恐怕有些同学就不是那么清楚了.

    有些人会用 ftp 之类的把日志下载下来本地再搜索, 如果是小一点的文件还好, 但日志文件往往都比较大, 因此这样的方式无疑是极为低效的.

    下面就介绍一种相对快捷的方式, 也不需要用到特别高级的命令, 仅需要 tail 和 grep 两个命令结合起来即可, 能达到这样一个效果:

    1. 能按关键字搜索;
    2. 在显示关键字所在行时还能高亮关键字;
    3. 能把关键字所在行的上下文, 比如上下 10 行的内容也一起显示出来.

    下面是一个效果示意图:

    tail grep log

    在这里, 我用我云主机的 nginx access log 做了个示范, 我搜索一篇文章 url 的关键字 "a-port", 然后显示出搜索的结果及上下文, 可以看到关键字被标红显示, 上下文也有显示, 多个搜索结果间以蓝色的短横间隔开来.

    下面具体说说怎么实现这样的搜索, 先具体讲讲各个命令及参数, 再说说怎么结合起来, 最后还给出一个脚本化的高级用法.

    tail 命令

    首先是 tail 命令. 因为查看日志通常从后面最新的日志去看, tail 命令就是从后往前找.

    比如下述命令会显示 access.log 的最后 10 行的内容:

    tail access.log

    tail 指定行数

    默认情况下, tail 只会显示最后的 10 行, 对于一个日志很多的应用来说, 这可能是不够的, 为此我们需要搜索更多的行.

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

    tail 可以结合 -n 参数指定一个行数, 比如下述命令会显示最后的 30 行的日志:

    tail -n 30 access.log

    注: 如果不太能记住参数, 还可以使用 -n 的完整命令参数 --lines:

    tail --lines 30 access.log

    grep 命令

    tail 仅能打印显示日志, 很多时候这是不够的, 日志通常非常多, 而且很多是没有用, 我们还需要能过滤, 或者说搜索筛选日志的内容, 这时就可以使用 grep 命令.

    grep 命令的基本用法是这样的. 假如你有一个文件 index.html, 你想在其中搜索一个关键词 official, 你可以这样用:

    grep official index.html

    结果如下:

    grep demo

    它会把关键字所在行给你显示出来, 并高亮关键字.

    关于高亮问题, 如果缺省没有高亮, 则可以自行加入 --color 选项, 像这样: grep --color official index.html

    注意, 通常不要直接用 grep 命令去搜索整个日志文件, 因为日志文件通常很大, 而且 grep 也是从开头开始搜索的, 因此可能搜索出一大堆你不感兴趣的历史记录.

    后面将介绍如何结合 tail 和 grep 命令以缩小搜索范围.

    带有空格的关键字

    如果关键字有多个单词并带有空格, 可以使用 '' 单引号引起来, 例如:

    grep 'english version' index.html

    grep 显示上下文

    有时, 我们不但要找出关键子所在行, 而且还想显示所在行上下的一些行.

    这在查找异常信息时非常常见, 一方面异常栈会打印成非常多行, 另外我们通常需要前前后后都看一下到底发生了什么.

    这时可以使用 grep 的 -NUM 参数来实现, 如下:

    grep -5 official index.html

    或者是使用 -C

    grep -C 5 official index.html

    它表示, 不但要找出 official 关键字所在行, 还要把所在行前后的 5 行都显示出来.

    • 后接的数字 5 就表示前后 5 行, 如果是 -10 就表示前后 10 行

    结果如下:

    grep with context demo

    grep 显示行号

    为了更清晰地呈现, 还可以选择显示行号, 用 -n 参数, 如下:

    grep -5 -n official index.html

    结果如下图:

    grep with context and line number demo

    可以看到, official 关键字在 21 行, 行头的行号还特别以冒号":" 标出; 此外, 关键行的前 5 行(16~20)和后 5 行(22~26)也一并显示了出来.

    如果我们是在跟踪一个异常, 这些上下文的信息可能会提供很多帮助.

    管道符的使用

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

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

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

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

    tail error.log | grep stream

    注意: grep 之前的竖杠 |.

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

    tail grep key word demo

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

    tail -n 20 error.log | grep -3 stream

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

    tail grep key word and context demo

    高级用法

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

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

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

    然后这样去用:

    ./search.sh stream 20 3

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

    tail -n 20 error.log | grep -3 stream

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

    ./search.sh stream

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

    自定义命令

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

    touch search.sh

    文件的内容如下:

    #!/bin/bash
    cd /usr/local/nginx/logs
    tail -n 20 error.log | grep --color -3 stream

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

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

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

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

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

    chmod 755 search.sh

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

    ./search.sh

    参数传递

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

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

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

    #!/bin/bash
    cd /usr/local/nginx/logs
    tail -n 20 error.log | grep --color -3 $1

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

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

    然后你这样

    ./search.sh hello

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

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

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

    #!/bin/bash
    cd /usr/local/nginx/logs
    tail -n $2 error.log | grep --color -$3 $1

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

    ./search.sh hello 1000 10

    就相当于:

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

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

    缺省值及判断逻辑

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

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

    #!/bin/bash
    lineCount=1000
    if [ $2 ]; then
    	lineCount=$2
    fi
    
    contextCount=10
    if [ $3 ]; then
    	contextCount=$3
    fi
    
    cd /usr/local/nginx/logs
    tail -n $lineCount error.log | grep --color -$contextCount $1

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

    如果只输入了关键字:

    ./search.sh hi

    结果就是这样:

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

    输入两个参数:

    ./search.sh hello 300

    结果就是这样:

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

    输入三个参数:

    ./search.sh hey 500 8

    结果就是这样:

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

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

    命令输出

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

    #!/bin/bash
    lineCount=1000
    if [ $2 ]; then
    	lineCount=$2
    fi
    
    contextCount=10
    if [ $3 ]; then
    	contextCount=$3
    fi
    
    cd /usr/local/nginx/logs
    echo "========= tail -n $lineCount error.log | grep --color -$contextCount $1"
    tail -n $lineCount error.log | grep --color -$contextCount $1

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

    总结

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

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

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

    作为一名程序员, 减少重复是我们的天职, 我们应该是怕重复, 怕麻烦的, 某种意义上, 我们应该是"懒惰"的:

    还记得 Perl 语言的发明人 Larry Wall 的话吗: "优秀程序员应该有三大美德:懒惰、急躁和傲慢(laziness, impatience and hubris)"

    更多关于抽象及重复的话题, 可以参考之前 计算机科学及重复性管理 专题, 关于使用 tail 结合 grep 查找日志关键字并高亮及显示所在行上下文就介绍到这里.

    展开全文
  • 查看日志经常碰到的一个需求就是按关键字去搜索, 在日常开发机子的 IDE , 都集成了强大的搜索功能, 但因为系统通常部署在 Linux 系统, 一般只有命令行界面, 在其应该怎么去搜索呢? 恐怕有些同学就不是那么...

    对于一个开发或运维人员而言, 当系统出现故障时, 第一步常常就是查看日志. 查看日志经常碰到的一个需求就是按关键字去搜索, 在日常开发机子上的 IDE 上, 都集成了强大的搜索功能, 但因为系统通常部署在 Linux 系统上, 一般只有命令行界面, 在其上应该怎么去搜索呢? 恐怕有些同学就不是那么清楚了.

    有些人会用 ftp 之类的把日志下载下来本地再搜索, 如果是小一点的文件还好, 但日志文件往往都比较大, 因此这样的方式无疑是极为低效的.

    下面就介绍一种相对快捷的方式, 也不需要用到特别高级的命令, 仅需要 tail 和 grep 两个命令结合起来即可, 能达到这样一个效果:

    能按关键字搜索;在显示关键字所在行时还能高亮关键字;能把关键字所在行的上下文, 比如上下 10 行的内容也一起显示出来.下面是一个效果示意图:

    2caf39f8138716f00a3850a18e46b336.png

    在这里, 我用我云主机的 nginx access log 做了个示范, 我搜索一篇文章 url 的关键字 "a-port", 然后显示出搜索的结果及上下文, 可以看到关键字被标红显示, 上下文也有显示, 多个搜索结果间以蓝色的短横间隔开来.

    下面具体说说怎么实现这样的搜索, 先具体讲讲各个命令及参数, 再说说怎么结合起来, 最后还给出一个脚本化的高级用法.

    tail 命令

    首先是 tail 命令. 因为查看日志通常从后面最新的日志去看, tail 命令就是从后往前找.

    比如下述命令会显示 access.log 的最后 10 行的内容:

    tailaccess.log

    tail 指定行数

    默认情况下, tail 只会显示最后的 10 行, 对于一个日志很多的应用来说, 这可能是不够的, 为此我们需要搜索更多的行.

    如果想实时查看日志, 可以参考之前的这篇文章使用 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

    结果如下:

    1f4b09ae96f4d4a3174c347b1ba1c480.png

    它会把关键字所在行给你显示出来, 并高亮关键字.

    关于高亮问题, 如果缺省没有高亮, 则可以自行加入 --color 选项, 像这样:grep --color official index.html

    注意, 通常不要直接用 grep 命令去搜索整个日志文件, 因为日志文件通常很大, 而且 grep 也是从开头开始搜索的, 因此可能搜索出一大堆你不感兴趣的历史记录.

    后面将介绍如何结合 tail 和 grep 命令以缩小搜索范围.

    带有空格的关键字

    如果关键字有多个单词并带有空格, 可以使用 '' 单引号引起来, 例如:

    grep'english version' index.html

    grep 显示上下文

    有时, 我们不但要找出关键子所在行, 而且还想显示所在行上下的一些行.

    这在查找异常信息时非常常见, 一方面异常栈会打印成非常多行, 另外我们通常需要前前后后都看一下到底发生了什么.

    这时可以使用 grep 的 -NUM 参数来实现, 如下:

    grep-5 official index.html

    或者是使用 -C

    grep-C 5 official index.html

    它表示, 不但要找出 official 关键字所在行, 还要把所在行前后的 5 行都显示出来.

    后接的数字 5 就表示前后 5 行, 如果是 -10 就表示前后 10 行

    结果如下:

    e9be88b21bd675348beb302b732831fe.png

    grep 显示行号

    为了更清晰地呈现, 还可以选择显示行号, 用 -n 参数, 如下:

    grep-5 -n official index.html

    结果如下图:

    0888526cdbf6e6cdbac4ec23a3b2d1fb.png

    可以看到, official 关键字在 21 行, 行头的行号还特别以冒号":" 标出; 此外, 关键行的前 5 行(16~20)和后 5 行(22~26)也一并显示了出来.

    如果我们是在跟踪一个异常, 这些上下文的信息可能会提供很多帮助.

    管道符的使用

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

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

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

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

    tailerror.log | grep stream

    注意: grep 之前的竖杠 |.

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

    91d145248667d1430bed03fc6841dd36.png

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

    tail-n20error.log|grep-3stream

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

    d45b09ffba250d294afc4f9e24141f36.png

    高级用法

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

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

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

    然后这样去用:

    ./search.shstream203

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

    tail-n20error.log|grep-3stream

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

    ./search.sh stream

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

    自定义命令

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

    touchsearch.sh

    文件的内容如下:

    #!/bin/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 这种脚本语言来说, 主要的问题是我们不熟悉其语法, 这个只要稍微查下它的手册或是在网上搜索下即不难知道.

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

    #!/bin/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 的上下文的行数也参数化:

    #!/bin/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 这种脚本语言, 最大的问题还是我们不熟悉其语法, 那么这个还是跟之前说的那样, 查查手册, 或搜索下, 过程就省略了, 具体来说, 可以这样:

    5b6955a125f199914c21e0a8b55acd61.png

    简单说就是定义两个变量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 这个命令来实现, 它同样支持变量:

    74637da76a103929c4011e015c3404da.png

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

    总结

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

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

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

    展开全文
  • 查看日志经常碰到的一个需求就是按关键字去搜索, 在日常开发机子的 IDE , 都集成了强大的搜索功能, 但因为系统通常部署在 Linux 系统, 一般只有命令行界面, 在其应该怎么去搜索呢? 恐怕有些同学就不是那么...

    对于一个开发或运维人员而言, 当系统出现故障时, 第一步常常就是查看日志. 查看日志经常碰到的一个需求就是按关键字去搜索, 在日常开发机子上的 IDE 上, 都集成了强大的搜索功能, 但因为系统通常部署在 Linux 系统上, 一般只有命令行界面, 在其上应该怎么去搜索呢? 恐怕有些同学就不是那么清楚了.

    有些人会用 ftp 之类的把日志下载下来本地再搜索, 如果是小一点的文件还好, 但日志文件往往都比较大, 因此这样的方式无疑是极为低效的.

    下面就介绍一种相对快捷的方式, 也不需要用到特别高级的命令, 仅需要 tail 和 grep 两个命令结合起来即可, 能达到这样一个效果:

    能按关键字搜索;

    在显示关键字所在行时还能高亮关键字;

    能把关键字所在行的上下文, 比如上下 10 行的内容也一起显示出来.

    下面是一个效果示意图:

    707dc4d2a5a9a90d0d44c74b88a487d6.png

    在这里, 我用我云主机的 nginx access log 做了个示范, 我搜索一篇文章 url 的关键字 "a-port", 然后显示出搜索的结果及上下文, 可以看到关键字被标红显示, 上下文也有显示, 多个搜索结果间以蓝色的短横间隔开来.

    下面具体说说怎么实现这样的搜索, 先具体讲讲各个命令及参数, 再说说怎么结合起来, 最后还给出一个脚本化的高级用法.

    tail 命令

    首先是 tail 命令. 因为查看日志通常从后面最新的日志去看, tail 命令就是从后往前找.

    比如下述命令会显示 access.log 的最后 10 行的内容:

    tail access.log

    tail 指定行数

    默认情况下, tail 只会显示最后的 10 行, 对于一个日志很多的应用来说, 这可能是不够的, 为此我们需要搜索更多的行.

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

    tail 可以结合 -n 参数指定一个行数, 比如下述命令会显示最后的 30 行的日志:

    tail -n 30 access.log

    注: 如果不太能记住参数, 还可以使用 -n 的完整命令参数 --lines:

    tail --lines 30 access.log

    grep 命令

    tail 仅能打印显示日志, 很多时候这是不够的, 日志通常非常多, 而且很多是没有用, 我们还需要能过滤, 或者说搜索筛选日志的内容, 这时就可以使用 grep 命令.

    grep 命令的基本用法是这样的. 假如你有一个文件 index.html, 你想在其中搜索一个关键词 official, 你可以这样用:

    grep official index.html

    结果如下:

    c718d01a8f22602d65903c41084d11ef.png

    它会把关键字所在行给你显示出来, 并高亮关键字.

    关于高亮问题, 如果缺省没有高亮, 则可以自行加入 --color 选项, 像这样: grep --color official index.html

    注意, 通常不要直接用 grep 命令去搜索整个日志文件, 因为日志文件通常很大, 而且 grep 也是从开头开始搜索的, 因此可能搜索出一大堆你不感兴趣的历史记录.

    后面将介绍如何结合 tail 和 grep 命令以缩小搜索范围.

    带有空格的关键字

    如果关键字有多个单词并带有空格, 可以使用 '' 单引号引起来, 例如:

    grep 'english version' index.html

    grep 显示上下文

    有时, 我们不但要找出关键子所在行, 而且还想显示所在行上下的一些行.

    这在查找异常信息时非常常见, 一方面异常栈会打印成非常多行, 另外我们通常需要前前后后都看一下到底发生了什么.

    这时可以使用 grep 的 -NUM 参数来实现, 如下:

    grep -5 official index.html

    或者是使用 -C

    grep -C 5 official index.html

    它表示, 不但要找出 official 关键字所在行, 还要把所在行前后的 5 行都显示出来.

    后接的数字 5 就表示前后 5 行, 如果是 -10 就表示前后 10 行

    结果如下:

    d8fe19ec2ce232b28e2bec8db782fdb2.png

    grep 显示行号

    为了更清晰地呈现, 还可以选择显示行号, 用 -n 参数, 如下:

    grep -5 -n official index.html

    结果如下图:

    365add24d912a7a6afca47586ca22462.png

    可以看到, official 关键字在 21 行, 行头的行号还特别以冒号":" 标出; 此外, 关键行的前 5 行(16~20)和后 5 行(22~26)也一并显示了出来.

    如果我们是在跟踪一个异常, 这些上下文的信息可能会提供很多帮助.

    管道符的使用

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

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

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

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

    tail error.log | grep stream

    注意: grep 之前的竖杠 |.

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

    7505163719c115d1bf198ddd80f96f26.png

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

    tail -n 20 error.log | grep -3 stream

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

    f7a565cdb13119412096ec61f1de2ce2.png

    高级用法

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

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

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

    然后这样去用:

    ./search.sh stream 20 3

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

    tail -n 20 error.log | grep -3 stream

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

    ./search.sh stream

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

    自定义命令

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

    touch search.sh

    文件的内容如下:

    #!/bin/bash

    cd /usr/local/nginx/logs

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

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

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

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

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

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

    chmod 755 search.sh

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

    ./search.sh

    参数传递

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

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

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

    #!/bin/bash

    cd /usr/local/nginx/logs

    tail -n 20 error.log | grep --color -3 $1

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

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

    然后你这样

    ./search.sh hello

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

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

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

    #!/bin/bash

    cd /usr/local/nginx/logs

    tail -n $2 error.log | grep --color -$3 $1

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

    ./search.sh hello 1000 10

    就相当于:

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

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

    缺省值及判断逻辑

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

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

    #!/bin/bash

    lineCount=1000

    if [ $2 ]; then

    lineCount=$2

    fi

    contextCount=10

    if [ $3 ]; then

    contextCount=$3

    fi

    cd /usr/local/nginx/logs

    tail -n $lineCount error.log | grep --color -$contextCount $1

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

    如果只输入了关键字:

    ./search.sh hi

    结果就是这样:

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

    输入两个参数:

    ./search.sh hello 300

    结果就是这样:

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

    输入三个参数:

    ./search.sh hey 500 8

    结果就是这样:

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

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

    命令输出

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

    #!/bin/bash

    lineCount=1000

    if [ $2 ]; then

    lineCount=$2

    fi

    contextCount=10

    if [ $3 ]; then

    contextCount=$3

    fi

    cd /usr/local/nginx/logs

    echo "========= tail -n $lineCount error.log | grep --color -$contextCount $1"

    tail -n $lineCount error.log | grep --color -$contextCount $1

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

    总结

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

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

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

    作为一名程序员, 减少重复是我们的天职, 我们应该是怕重复, 怕麻烦的, 某种意义上, 我们应该是"懒惰"的:

    还记得 Perl 语言的发明人 Larry Wall 的话吗: "优秀程序员应该有三大美德:懒惰、急躁和傲慢(laziness, impatience and hubris)"

    更多关于抽象及重复的话题, 可以参考之前 计算机科学及重复性管理 专题, 关于使用 tail 结合 grep 查找日志关键字并高亮及显示所在行上下文就介绍到这里.

    展开全文
  • 查看日志经常碰到的一个需求就是按关键字去搜索, 在日常开发机子的 IDE , 都集成了强大的搜索功能, 但因为系统通常部署在 Linux 系统, 一般只有命令行界面, 在其应该怎么去搜索呢? 恐怕有些同学就不是那么...
  • 查看日志经常碰到的一个需求就是按关键字去搜索, 在日常开发机子的 IDE , 都集成了强大的搜索功能, 但因为系统通常部署在 Linux 系统, 一般只有命令行界面, 在其应该怎么去搜索呢? 恐怕有些同学就不是那么...
  • 一般来说,我们是通过grep命令查找文件中关键字所在的行,但是只能得到有关键字出现的行,他没有上下文,这时候,需要借助一些grep选项了。 这里通过示例说明一下: 查看关键字前后5行的内容 grep -C 5 ...
  • linux查找日志技巧2

    2017-12-16 23:11:30
    情景:文件太大,无法用vi查询  1)可以用grep命令... -C : 匹配的上下文显示行数  -A : 匹配的行下显示的行数  -B : 匹配的行上显示的行数  2)如果匹配的行数很多,可以写入一个文件,然后用vi查看:grep
  • 本文总结一下 shell 查看日志的脚本 首先在我们开发的过程中不管我们是做什么开发,java也好数据库也好都会在服务器上产生大量的日志...1 能够按照我们要查找的关键字查找并给出上下文,打印在终端。 2 能够设置上...
  • 有时候在 Unix 系统上查找信息如同大海捞针。如果重要的信息被淹没在大量文本中,它们也很难被注意到。...grep 命令可以帮助你找到任意文本,特定单词,文本模式和有上下文的文本。当你知道文本长什么样时,查找它通常
  • 整体解决方案:AOP切面日志 + 日志链(MDC + TraceId) ...日志链(MDC + TraceId):有利于查找错误发生时的上下文日志。 详情参照 :https://download.csdn.net/download/CSDN_WANGQI/13772869 ...
  • 访问以提问或在Twitter通过查找我们。 变更日志 检查以获取的最新更新。 贡献 请参阅我们的 维护者 斯科特·伯恩( )– Forestry.io DJ Walker( )– Forestry.io 所有贡献者 :sparkles: 感谢这些很棒的人...
  • SpringCloud之个性化日志追踪

    千次阅读 2019-01-04 12:59:37
    当需要排查一些问题时,可以根据报错的上下文进行分析,给问题诊断带来方便。在spring cloud微服务中,单体应用的日志跟踪技术已经不能满足需求,因而一般采用Spring Cloud Sleuth组件提供的功能来完成分布式日志...
  • linux下某个文件中查找文件内容

    千次阅读 2011-09-29 11:34:28
    对于日志文件,有时候不希望打包下载下来,如何查找并查看上下文的内容呢? 可以使用more命令打开文件  more aaa.log 然后使用子命令 进行查找操作 向下查找: /要找的关键字 向上查找 ?要找的...
  • linux查找命令总结

    2017-08-18 16:47:23
    由于grep只能匹配关键字,不能显示关键字上下的内容,所以先打出关键字的行号,再根据行号打出上下文。 - -根据关键字查询并打出行号 cat -n test.log |grep 'keyword' -- 假设keyword信息在159行,为了查看前后10...
  • 自制日志小软件EveryDR

    2012-02-12 18:45:08
    下载源文件  大概经历了半个月的时间,... 此间经历的最头疼的一件事就是在响应WM_PAINT消息时,函数中用了CDC 来获取设备上下文,正因为此而纠结了很长一段时间,实际上再响应该消息时应该选择CPaintDC 以前我也经
  • 由于我们通过CAT命令已经知道行号了,只需要使用SED,输入一个行号的大概范围,就可以详细的展示上下文日志内容了。 小技巧 如果公司里没有完善的查看日志的工具,例如ELK。那么借助上面的小工具,也可以简单的...
  • 其它服务:对话上下文,缓冲,日志
  • 先看看错误; 在查找启动时的日志; 仔细查找出错的地方,然后看看上下文;错误很明显了,日志文件被锁住了,在加载jta日志配置时尝试写入报错
  • 解决:其中激活上下文文件,找不到从属集的有:opencv_core230d.dll,opencv_legacy230d.dll,opencv_highgui230d.dll,opencv_imgproc230d.dll等。找到对应的缺失文件放入.exe文件夹下,依旧报错。。。 问题...
  • 走进LINUX

    2019-04-26 10:12:05
    1.日志文件中查找关键字,并显示上下行的内容 grep -C3 “key” fileName 注意 C 是大写字母,显示key的上下3行的内容 ...2.根据行号查看上下文内容 sed -n “开始行,结束行p” fileName 注意 p 代码段落 ...
  • 定位生产问题的方法

    2020-11-23 09:30:56
    下载或者直接查看生产日志,通过查找上下文或者当前操作关键字的方法,找到生产问题发生时间的日志。如果是页面有报错的,可以直接在问题发生时间范围内查找error或者exception日志。 认真分析代码,找到出问题的...
  • 如何快速定位线上问题?

    千次阅读 2017-10-29 22:07:20
    I、登录环境 使用合适的工具快速登录环境是解决线上问题的前提。...c、异常情况日志更详细,日志最好包含上下文,这样可以省去不少定位时间。III、问题定位 1、单纯根据某明显的文本特征去查找某段日志 grep
  • JAVA百实例源码以及开源项目

    千次下载 热门讨论 2016-01-03 17:37:40
    5个目标文件,演示Address EJB的实现,创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口...
  • 5个目标文件,演示Address EJB的实现 ,创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口...

空空如也

空空如也

1 2 3 4 5
收藏数 91
精华内容 36
关键字:

日志上下文查找