使用命令行分析日志文件

m3ng9i 发表于

文本文件是一种结构简单,被广泛使用的文件类型。通常我们可以使用操作系统自带的软件查看文本文件的内容,但是对于包含大量数据的日志文件,如果要查看和提取其中的信息,使用普通的编辑器往往无法达到一个好的效果。当文件过大时,普通的编辑器可能会无法打开或者反应变慢。在一个大的日志文件中查找数据时,使用图形界面的编辑器进行操作会显得十分繁琐。这种情况下,使用命令行来观察和分析文件就是一种方便和有效的方法。

如果你使用的是 Linux/Mac,那么本文介绍的命令都可以直接在操作系统的命令行界面中使用。如果你使用的是 Windows ,可以安装一个叫做 Cygwin 的软件,为 Windows 带来一个类似 Unix 的命令行运行环境。

本文假设你对基本的命令行操作有所了解,例如知道如何打开命令行程序窗口、可以查看和切换目录等。

以下示例使用了一个文件名为 example.log 的文件,内容包括时间、地区、用来表示订单号和金额的数字。这些数据使用程序随机生成,各字段由制表符分隔。你可以 点此 下载这个文件。

查看文件概况

使用 cat 命令可以查看文件的完整内容,如果要查看 example.log 的内容,可以输入以下命令:

cat example.log

运行结果:

cat命令

当命令输入完毕并回车后,文件的内容便显示在了命令行界面的窗口中。如果文件的内容很多,就会在窗口中不断的滚动直到将文件内容都输出完毕,如果你要尽早结束输出,可以按下 CTRL+C 键停止 cat 命令的输出。

你可以在输出的结果中为每一行内容添加编号,只需要给 cat 命令添加一个 -n 参数即可实现:

cat -n example.log

运行结果:

使用cat命令显示行号

另一个查看文件内容的命令是 more ,举例:

more example.log

对于超过一屏内容的文件,在输出一屏后, more 会自动暂停。暂停后,你可以按回车键输出下一行内容,按空格键输出下一屏内容,按 q 退出。运行效果:

more命令

另外两个比较实用的命令是 headtail ,它们分别可以输出文件的前 10 行或后 10 行。在观察比较大的文件结构时,这两个命令非常有用。举例:

输出前 10 行:

head example.log

输出后 10 行:

tail example.log

可以在 head 或 tail 命令后面加上参数: -数字 自定义输出的行数,举例:

输出前 3 行:

head -3 example.log

输出后 5 行:

tail -5 example.log

如果要统计一个文件的行数,可以使用 wc 命令,举例:

wc -l example.log

wc 命令的 -l 参数的含义是:只输出文件的行数。如果不加这个参数,那么会同时统计文件的行数、单词数和字节。这个命令可以很方便的让我们了解文件的规模。下图可以看出,example.log 文件共有 1000 行。

wc命令

也可以使用通配符显示多个文件的行数。例如,wc -l *.log 命令会统计当前目录下每个扩展名为 log 的文件的行数,同时此命令也会统计这些文件的总行数。如下图:

wc命令显示多个文件的行数

如果你要统计一个文件的字符数,可以使用 -m 参数。在你写完一篇纯文本格式的文章后,这个命令可以很方便的进行字数统计。举例:

wc -m example.log

在文件中查询信息

使用 grep 命令可以将文件中包含特定文字的行抽取出来。例如,grep 河北 example.log 命令会扫描整个文件,如某一行包含「河北」则会显示这一行内容:

grep命令

使用 grep -v 命令可以将包含特定文字的行排除。例如,运行命令 grep -v 山西 example.log 后会输出所有不包含「山西」的行。

你也可以使用正则表达式进行更复杂的信息提取。命令 grep -E "北京|上海" example.log 会提取出包含「北京」或「上海」的行,如下图:

grep命令-正则表达式

抽取部分数据

使用 cut 命令可以很方便的从文本文件中抽取部分数据。例如,抽取第 1 和第 3 列数据:

cut -f 1,3 example.log

运行结果如下:

cut命令

cut 命令的 -f 参数表示提取若干字段的数据,后面的 1,3 表示需要的字段序号。如果需要提取 2 至 4 字段,除了使用 -f 2,3,4 参数,也可以用 -f 2-4 来表示:

cut -f 2-4 example.log

对于 cut 命令,制表符为默认的字段分隔符。如果要将其它字符设置为字段分隔符,则需要使用 -d 参数,举例如下:

cut -d : -f 2 example.log

上例将字段分隔符设置为冒号,并提取出第 2 个字段的数据,也就是时间字段中的「分钟」那一列。运行结果如下:

cut命令,设置字段分隔符

除了按字段提取数据,也可以按字符来提取,这时要用到 -c 参数。举例如下:

cut -c 6-16 example.log

以上命令提取出第 6 至 16 个字符,也就是日志中的月、日、时、分的部分。运行结果如下:

cut命令,按字符提取

排序

example.log 日志内容并不是按照时间排序的,如果需要排序后的结果,可以使用 sort 命令:

sort example.log

由于 example.log 的时间字段正好在第一列的位置,因此上面的命令运行结束后便自动按时间字段排好顺序:

sort命令

如果要根据其他字段排序,可以使用 -k 参数,下例会根据 example.log 文件的第 3 个字段排序:

sort -k 3 example.log

运行结果如下:

sort命令-k参数

sort 还有其它几个参数十分常用:

-t  指定字段分隔符(配合 -k 参数使用)
-r  逆序排序
-R  随机排序(Mac OS X 不支持此参数) 
-u  去掉重复的行

使用管道组合多个命令

Linux/Unix 命令行强大的地方就是可以利用管道连接多个命令。管道符为 | ,你可以这样使用管道:

命令1 | 命令2 | 命令3 ...

管道符左边的命令产生的输出将会作为管道符右边命令的输入。上例中「命令1」的运行结果变成了「命令2」的原始数据,「命令2」将「命令1」输出的运行结果处理完毕后,传送给了「命令3」,「命令3」将「命令2」运行的结果处理完毕后,如果还有下一个命令,则将运行结果继续传递给下一个命令使用,否则就将运行结果显示在命令行窗口中。

管道符就像串糖葫芦一样,将多个命令串了起来。我们可以根据自己的需要,利用管道符将多个命令组合起来,完成更复杂的数据处理工作。下面是几个例子:

根据某个字段出现的次数进行统计:

cut -f 2 example.log | sort | uniq -c | sort

上面的例子提取出 example.log 中的「地区」字段(由 cut -f 2 example.log 命令实现),统计其在整个文件中出现的次数(由 uniq -c 命令实现),并按照从少到多进行排序(由第二个 sort 命令实现)。提供给 uniq -c 命令的数据必须是已排序的数据,否则将会得出错误的运行结果,因此在 uniq -c 前面还有一个 sort 命令。运行结果如下:

管道1

计算 example.log 文件中,地区为「北京」的订单的平均金额:

grep 北京 example.log | cut -f 4 | awk 'BEGIN{sum=0}{sum+=$0}END{print sum/NR}'

上面的例子取出包含「北京」的行(由 grep 北京 example.log 命令实现),然后取出金额字段(由 cut -f 4 命令实现),最后将所有金额相加,并除以日志条数计算出订单平均金额(由 awk 'BEGIN{sum=0}{sum+=$0}END{print sum/NR}' 命令实现)。运行结果如下:

管道2

统计 example.log 文件中包含多少个地区:

cut -f 2 example.log | sort -u | wc -l

上例先用 cut -f 2 抽取出包含「地区」信息的字段,然后使用 sort -u 进行剔重(去除重复数据),最后用 wc -l 来统计数据个数。运行结果如下:

管道3

将运行结果保存到文件中

前面的例子都将运行结果直接输出到命令行窗口,如果想要将运行结果保存到文件中,可以使用 > 将输出重定向到一个文件中。例如,下例根据日期统计订单数量,最后使用 > new.log 将最终结果保存到 new.log 文件。

cut -d " " -f 1 example.log | sort | uniq -c > new.log

在命令运行完毕后,我们还可以使用 cat 命令来查看这个新生成的文件的内容,如图:

重定向到文件

获取帮助

以上介绍的部分命令可以使用 -h--help 参数获取帮助信息,如果要查看详细的使用手册,可以使用 man 命令名称 来查阅。举例:

man grep

阅读推荐