让工作更有效率的linux命令(less/zless/tail/head/grep/zgrep/which/whereis/locate/find/awk)

 

作为一个研发苟,linux命令是命令是必须会一些的,不一定要求会很多,至少常用的要清楚,这样排查问题或者分析才会更加有效。这篇笔记会记录一些常用的linux命令,不在于每一个命令的所有参数都拿出来细说,而是主要服务于日常使用。

一、文件中查找

该类命令包括less/zless,tail/head,grep/zgrep

less/zless

less是一个在文件中快速查找指定内容的命令,more也有类似的功能,但是more命令比较原始,功能较less少,所以掌握了less后more就没有必要了。less使用方式如下:

[root@VM_0_14_centos test]# less test
1,2,3,4,5,000
1,s,e,w,f,222
a,2,3,4,5,000
1,b,c,d,e,111
1,2,3,4,5,000
1,2,3,4,5,000
a,b,c,d,e,111
1,2,3,4,5,000
a,b,c,d,e,111
1,b,c,d,e,111
a,s,e,w,f,222
a,s,e,w,f,222

 

 需要查找某个子串的时候,输入‘/’字符,并在‘/’后面输入想要查找的字串,最后点击回车开始查找:

a,s,e,w,f,222
a,s,e,w,f,222
/3

 如果字串在文件中多次出现,可以按n查找下一个,N查找上一个。'?'的功能与’/‘类似,只是'?'下n/N的作用与’/'相反。

另外,less打开文件后,还有一些快速跳转的功能,比如翻页为pagedown/pageup,快速跳转到文件头和文件尾分别为g/shift+g(G)。

zless是less读取压缩文本文件的版本。通常我们的线上服务会记录很多服务的日志,并且每天归档为zip文件,那么在分析之前的文件的时候less就不起作用了,这个时候就需要使用zless。

tail/head

 tail和head的作用是从文件尾部或者文件头部取出固定行数的内容,tail取文件最后n行,head取文件开头n行,由于只有取的位置不一样,这里以tail为例。

tail filename    // 默认取最后10行
tail -n  -9  filename     // 取最后9行,可以缩写为 tail -9 filename

上面两种种比较常用,下面还有两种不常用的使用方式

tail -f filename    // 可以感知文件刷新
tail -n +10 filename    // 获取第10行及以后的行

# 例子
cat test | wc -l    // 12,test文件总共12行
tail -n +10 test   
/*
a,b,c,d,e,111
a,s,e,w,f,222
a,s,e,w,f,222
*/

grep/zgrep

grep是从文件中过滤包含指定字串的行,zgrep是从文本文件的压缩文件中过滤。zgrep和grep的功能是类似的,这里以grep说明。

通常,如果要找到子串,可以使用less命令,再使用‘/’符号匹配。但这样步骤多了,另一种快速的方法就是使用grep命令。

简单用法

grep '子串‘ filename  

上面的用法比较简单,适用于只需要找到包含子串的某一行的情况。但是很多情况下,我们还需要当前行后面的几行,比如用用抛出的异常去错误日志里匹配的时候,我们还会想要看到错误栈信息以便于分析问题,这个时候可以使用下面的方式

grep -A '子串’ filename 

 上面的这种方式处理可以返回子串所在的行,还可以返回紧挨着子串的下面一行。其中的参数A意思为After。同样的参数还有C和B,C代表context,返回子串所在行的前面n行和后面n行;B代表before,返回子串所在行前面的n行:

grep -B '子串’ filename 
grep -C '子串’ filename 

 

二、文件查找命令

 在平时的工作中,我们经常会有查找某个文件位置的需求。比如安装了某个软件之后,忘记安装位置了,那么相关的配置文件就不好找,或者以前创建的某个文件忘记位置了,等等。查找文件常用的命令有which、whereis、locate、find。

which

which是用于寻找可执行文件的命令,这里的“可执行文件”指的是PATH这个环境变量所规范的路径(注意,这里是不查找history等bash内置的命令),使用方式为:

which  [-a]  command 

默认是查找到PATH路径下第一个符合条件的文件,加上a条件后会找到所有符合的文件。

例如

[root@VM_0_14_centos test]# which ifconfig
/usr/sbin/ifconfig

whereis

whereis只查找某些特定目录下的文件,使用方式如下:

whereis  [-bmsu] 文件名
-l :可以列出
whereis 会去查询的几个主要目录而已 -b :只找 binary 格式的文件 -m :只找在说明文档 manual 路径下的文件 -s :只找 source 来源文件 -u :搜寻不在上述三个项目当中的其他特殊文件

注意到,上面的可选参数中是没有-l的,这是因为使用whereis -l的时候,后面不需要跟文件名。

whereis使用例子:

[root@VM_0_14_centos test]# whereis ifconfig
ifconfig: /usr/sbin/ifconfig /usr/share/man/man8/ifconfig.8.gz

 具体会查找哪些目录,可以在查找的时候使用-l参数查看,如下展示了部分内容:

[root@VM_0_14_centos ~]# whereis -l

bin: /usr/bin
bin: /usr/sbin
bin: /usr/lib
bin: /usr/lib64
bin: /etc
bin: /usr/etc
bin: /usr/games
bin: /usr/local/bin

...

 locate

locate是利用数据库来搜索文件名,linux系统会为系统内的文件创建一个数据库,所以查找速度非常快。但是有一个弊端就是该数据默认每天更新一次,新增的文件有可能会查不到。可以使用updatedb来更新数据库文件,但是会等待一段时间。

updatedb:根据 /etc/updatedb.conf 的设置去搜寻系统硬盘内的文件名,并更新 /var/lib/mlocate 内的数据库文件
locate:依据 /var/lib/mlocate 内的数据库记载,找出使用者输入的关键字文件名

数据库位置如下所示:

[root@VM_0_14_centos mlocate]# ll /var/lib/mlocate
-rw-r----- 1 root slocate 3624726 Feb 18 03:40 mlocate.db

loate使用方式如下:

locate [-ir] keyword

-i :忽略大小写的差异;
-c :不输出文件名,仅计算找到的文件数量
-l :仅输出几行的意思,例如输出五行则是 -l 5
-S :输出 locate 所使用的数据库文件的相关信息,包括该数据库纪录的文件/目录数量等
-r :后面可接正则表达式的显示方式

find

find命令功能很全,可以根据时间查找文件,也可以根据使用者或者群组查找文件,以及根据文件名或者文件权限查找。它的缺点是速度比较慢。本笔记只是记录工作中经常使用的方法,所以,只展示一下使用文件名如何查找,其他的查找方式可以通过man手册或者参照《鸟哥的Linux私房菜基础学习篇第四版》第6.5.2节。

 

find path -name filename  // 根据文件名查找文件

// 在/root路径下查找名为test的文件
[root@VM_0_14_centos ~]# find /root -name test
/root/test
/root/test/test

 

三、数据处理命令awk

awk

1. awk是什么呢?

首先awk是一个linux下的一个命令,使用which命令可以看到

[root@VM_0_14_centos ~]# which awk
/usr/bin/awk

同时,awk也是一种语言,使用man awk可以看到如下的两句描述:

/**
  * gawk - pattern scanning and processing language
  *  
  * Gawk is the GNU Project's implementation of the AWK 
  * programming language.
*/

其基本用法如下:

awk [-F 分隔符] '条件1{语句1}条件2{语句2}...'  文件名

2. awk可以做什么?

awk主要是用于分析文本里的数据的,举一个简单的例子,比如要获取最近前五个登陆者的用户名和登陆ip该怎么做呢?首先可以使用last命令获取到前五个登陆者

[root@VM_0_14_centos ~]# last -n 5
root     pts/0        111.230.154.177  Fri Feb 19 15:43   still logged in   
root     pts/1        119.29.96.147    Fri Feb 19 15:22 - 15:38  (00:15)    
root     pts/0        119.28.22.215    Fri Feb 19 15:10 - 15:24  (00:14)    
root     pts/1        111.230.154.177  Thu Feb 18 16:18 - 16:35  (00:17)    
root     pts/0        119.29.96.147    Thu Feb 18 16:02 - 16:21  (00:18) 

通过分析可以知道,每一行的第一列和第三列分别代表了登陆者的用户名和登陆ip,使用awk命令可以很容易地把这两个信息单独过滤出来

[root@VM_0_14_centos ~]# last -n 5 | awk '{print $1 "\t"  $3}' // awk中的条件被省略了
root    111.230.154.177
root    119.29.96.147
root    119.28.22.215
root    111.230.154.177
root    119.29.96.147

上面表达式中的$1,$3分别是每一行第一列和第三列的变量名,注意,$0是整行记录的变量名。

awk处理文本的过程为:

  a.依次读取文本中的每一行

  b.使用分割符对该行内容进行分割并填入$0,$1..等中

  c.对该行数据应用'条件1{语句1}条件2{语句2}...'中的表达式。

3. awk的使用

首先,新建一个有12行命令的测试文件test,文件有多少行可以使用wc -l  filename

1,2,3,4,5,000
1,s,e,w,f,222
a,2,3,4,5,000
1,b,c,d,e,111
1,2,3,4,5,000
1,2,3,4,5,000
a,b,c,d,e,111
1,2,3,4,5,000
a,b,c,d,e,111
1,b,c,d,e,111
a,s,e,w,f,222
a,s,e,w,f,222

awk的默认分割符是空格和tab,如果需要指定分隔符的话,可以使用-F参数或者在表达式中指定,如下

 // 方式1
awk -F ',' '{print $1 "\t"  $6}' test

// 方式2
awk  'BEGIN{FS=","}{print $1 "\t"  $6}' test

// 输出
1       000
1       222
a       000
1       111
1       000
1       000
a       111
1       000
a       111
1       111
a       222
a       222

 方式中使用在第一个{}中预定义了分隔符变量FS,使用BEGIN作为条件的目的是使设置的分隔符在第一行就生效,如果不使用BEGIN,那么设置的分隔符在第二行才会生效。BEGIN及其后{}中的语句只会执行一次,主要是做初始化的用途;同样的还有END条件,它用来做收尾工作,类似于java中的finally。

上面说到了分割符变量,其实awk还有两个常用的分隔符变量:NF(每一行拥有的字段总数)、NR(目前awk所处理的数据的行数)

[root@VM_0_14_centos test]# awk  'BEGIN{FS=","}{print "当前行数\t" NR "\t字段数\t" NF "\t"  $1 "\t"  $6}' test
当前行数        1       字段数  6       1       000
当前行数        2       字段数  6       1       222
当前行数        3       字段数  6       a       000
当前行数        4       字段数  6       1       111
当前行数        5       字段数  6       1       000
当前行数        6       字段数  6       1       000
当前行数        7       字段数  6       a       111
当前行数        8       字段数  6       1       000
当前行数        9       字段数  6       a       111
当前行数        10      字段数  6       1       111
当前行数        11      字段数  6       a       222
当前行数        12      字段数  6       a       222

awk中同样支持类似于c语言的逻辑运算符,这一块不详细展开了,下面只举一个例子

[root@VM_0_14_centos test]# awk  'BEGIN{FS=","}{if($6 == '222') {print "当前行数\t" NR "\t字段数\t" NF "\t"  $1 "\t"  $6}}' test
当前行数        2       字段数  6       1       222
当前行数        11      字段数  6       a       222
当前行数        12      字段数  6       a       222

 

最后再举一个我在实际工作中会经常使用到的一个例子。

我负责的系统有一个monitor日志,其中的每一行记录了其他系统调用我们的系统的信息及调用结果。以test文件为例,000代表成功码、111代表失败码、222代表异常码,第一列中的1和a分别代表了不同的接口。那么在系统发布到生产环境的时候,为了分析系统调用是否正常,我们每次都需要分析各个接口的调用情况,比如接口a成功的调用有多少,异常的调用有多少。下面就给出一个使用awk命令的语句实现上面的功能

[root@VM_0_14_centos test]# awk -F ',' '{print $1 "\t" $6}' test | sort | uniq -c 
      4 1       000  // 输出的第一列表示文件中有多少行跟后面两列一致的
      2 1       111
      1 1       222
      1 a       000
      2 a       111
      2 a       222

对上面的语句做一下解释。第一部分,对test文件的每一行进行过滤,拿到第一列和第六列的内容;第二部分,对过滤后的内容进行排序,使得第一列(接口)和第二列(返回结果码)分别按顺序排列;第三部分使用uniq命令对排序后的行进行统计,uniq是一个报告或者忽略重复行的命令,本例中的-c是对紧挨着的相同行进行统计。

 

参考:

 [1] 鸟哥.《鸟哥的Linux私房菜基础学习篇》第四版

 [2] https://www.cnblogs.com/ginvip/p/6352157.html

posted @ 2021-02-08 17:28  不吃陈皮  阅读(2288)  评论(0编辑  收藏  举报