让工作更有效率的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