Linux进阶
一、Linux进阶补充
1.wc命令
语法:wc [选项] 文件…
说明:该命令统计给定文件中的字节数、字数、行数。如果没有给出文件名,则从标准输入读取。
wc -l file 统计行数
wc -w file 统计单词数
cat file | wc -c 统计字符数
wc file 分别打印出文件的行数、单词数和字符数
find test/ -name "*.js" |wc -l 统计test目录下,js文件数量
2.输入/输出重定向
| 命令 | 说明 |
|---|---|
| > file | 将输出重定向到另一个文件file |
| >> file | 将输出以追加的方式重定向到file |
| < file | 将输入重定向到file |
3.文件描述符
文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创建的索引,当某个程序打开文件时,操作系统返回相应的文件描述符,程序为了处理该文件必须引用此描述符。程序刚刚启动的时候,0是标准输入,1是标准输出,2是标准错误。如果此时去打开一个新的文件,它的文件描述符会是3。
标准文件描述符号如下:
| 文件描述符 | 用途 | POSIX名称 | stdio流 |
|---|---|---|---|
| 0 | 标准输入(数据输入到程序中) | STDIN_FILENO | stdin |
| 1 | 标准输出(程序打印的数据,默认为终端) | STDOUT_FILENO | stdout |
| 2 | 标准出错(对于错误消息,也默认为终端) | STDERR_FILENO | stderr |

举例:
(1)把当前的标准输出重定向到test文件中
[root@localhost ~]# echo 'test01' 1> test
[root@localhost ~]# cat test
test01
(2)把当前的标准输入重定向到test文件中
#接上面操作
[root@localhost ~]# read user 0< test
[root@localhost ~]# echo $user
test01 #user变量输入为test里的文本内容
(3)把当前标准出错输入到重定向test文件
[root@localhost ~]# ls -l test111
ls: 无法访问test111: 没有那个文件或目录
[root@localhost ~]# ls -l test111 2> error.txt #STDERR是流号2,使用该种数字来标识流。如果在>运算符之前放置一个数字,则它将重定向该流(如果不使用那样使用数字,则默认为流1)。
[root@localhost ~]# cat error.txt
ls: 无法访问test111: 没有那个文件或目录
(4)分配其他的文件描述符
[root@localhost ~]# exec 6>test #文件描述符6指向test文件
[root@localhost ~]# echo 'test 6' 1>&6 #不像描述符1,所有的输出都会自然找它,所以像找描述符6的时候要用&来引用它。
#这条命令就将输出指向到了描述符6,然后描述符6又将内容重定向到test文件。
[root@localhost ~]# cat test
test 6
详细可参考:Linux 文件描述符详解,最后还附有管道和重定向之间的区别。
4.lsof命令
lsof(list open files)是一个列出当前系统打开文件的工具。在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。
lsof语法格式是: lsof [options] filename
在终端下输入lsof即可显示系统打开的文件,输出内容包含信息如下:

COMMAND:程序的名称
PID:进程标识符
USER:进程所有者
FD:文件描述符,应用程序通过文件描述符识别该文件
TYPE:文件类型,如 DIR、REG 等
DEVICE:以逗号分隔设备编号
SIZE:文件的大小(bytes)
NODE:索引节点(文件在磁盘上的标识)
NAME:打开文件的确切名称
常用的参数列表:
lsof filename 显示打开指定文件的所有进程
lsof -a 组合多个选项,选项间默认是或的关系,-a可以将选项间关系变为与
lsof -c <进程名> 输出指定进程所打开的文件
lsof -u username 显示所属user进程打开的文件
lsof -g gid 显示归属gid的进程情况
lsof +d /DIR/ 显示目录下被进程打开的文件
lsof +D /DIR/ 同上,但是会搜索目录下的所有目录,时间相对较长
lsof -d FD 显示指定文件描述符的进程
lsof -n 不将IP转换为hostname,缺省是不加上-n参数
-i 选项用来查看被打开的和网络相关的文件,其参数的格式如下:
[46][protocol][@hostname|hostaddr][:service|port]
46 表示 IP 协议的版本(IPV4、IPV6)
protocol 表示网络协议的名称,比如 TCP 或 UDP
hostname 或 hostaddr 表示主机地址
service 指 /etc/services 中的名称,比如 smtp 或多个服务的列表
port 表示端口号,可以指定一个或多个
lsof命令常见用法举例:
(1)查看哪些进程打开了某个文件
如下查询打开了 /bin/bash 文件的进程,
[root@localhost ~]# lsof /bin/bash
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 1291 root txt REG 253,0 964536 50336671 /usr/bin/bash
bash 1310 root txt REG 253,0 964536 50336671 /usr/bin/bash
(2)查看哪些进程打开了某个目录以及目录下的文件
+d 选项不执行递归查询,如下

+D 选项会对指定的目录进行递归查询,如下:

在卸载文件系统时,如果有进程打开了该文件系统中的文件或目录,卸载操作就会失败。因此在卸载文件系统前最好通过 lsof +D 检查文件系统的挂载点,杀掉相关的进程然后再执行卸载操作。
(3)查看某个进程打开的所有文件

(4)组合多个选项查看
如果为 lsof 命令指定多个选项,这些选项间默认是或的关系,满足任何一个选项的结果都会被输出。可以添加额外的 -a 选项,它的作用就是让其它选项之间的关系变为与,比如下面的命令:
[root@localhost ~]# lsof -a -p $$ -d0,1,2
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 1310 root 0u CHR 136,0 0t0 3 /dev/pts/0
bash 1310 root 1u CHR 136,0 0t0 3 /dev/pts/0
bash 1310 root 2u CHR 136,0 0t0 3 /dev/pts/0
-p选项指定当前进程的PID
-d 选项则用来指定进程打开的文件描述符(可以通过逗号分隔多个文件描述符)
-a 表示-p和-d同时满足的才输出
(5)通过指定程序的名称查看打开的文件
losf -c

(6)lsof -i 查看被打开的与网络相关的文件
-i 选项默认会同时输出 IPv4 和 IPv6 打开的文件

只列出IPv4 或 IPv6 打开的文件

列出与22号端口相关的文件

(7)统计系统打开的文件总数

命令中的 -P 选项表示不解析端口号,-n 选项表示不解析主机名,这两个选项主要的目的是为了提升 lsof 命令的执行速度。
5.管道中使用变量
管道是独立的进程,执行完即销毁,使用()或是while组合可以编写复杂的控制逻辑。
如下方式无法获取到变量x的值:
echo hello world | read x;echo $x
在管道中使用变量,如下方法可以获得变量x:
方法一:
echo hello world | (read x;echo $x;
方法二:
[root@localhost ~]# echo hello world | while read x; do
> echo $x;
> done
hello world
6.grep命令补充
grep -E pattern file 使用扩展正则表达式
grep pattern -r dir/ 递归搜索
grep -A -B -C pattern file 打印命中数据得上下文(-Bn 前n行,-An 后n行,-Cn 前n行+后n行)
7.BRE基本正则表达式
| 代码 | 说明 |
|---|---|
| ^ | 开头 |
| $ | 结尾 |
| [a-z] [0-9]区间 | 如果开头带有^表示不能匹配区间内得元素 |
| * | 0个或多个 |
| . | 表示任意字符(除换行符以外) |
8.ERE扩展正则表达式
(1)ERE是在基本正则表达式(BRE)基础上的扩展,基本的扩展正则如下:
| 代码 | 说明 |
|---|---|
| ? | 非贪婪匹配(最多一次匹配,也就是0次或1次匹配) |
| + | 至少一次匹配(一次或多次匹配) |
| () | 用于分组,BRE中只将()当作普通字符对待,要使用此功能必须加\进行转义,即“\(\)” |
| {} | 范围约束,用于表示重复匹配的次数;BRE中只将{}当作普通字符对待,要使用此功能必须加\进行转义,即“\{\}” |
| | | 匹配多个表达式的任何一个 |
(2)grep、awk、sed开启ERE
grep:grep -E

awk: awk ‘/ /’

sed:sed -E
[root@localhost ~]# echo "test" | sed -E "s/t|s/2/g"
2e22 #开启了ERE,将t或s都换成了2
9.awk小技巧
(1)用awk命令查看第一行,用空格分隔的每列对应的$号,是$1还是KaTeX parse error: Expected '}', got 'EOF' at end of input: …+) print i" = "i}’ test.text
test.text文件内容如下:

执行命令后,返回如下:
1 = b2423534
2 = test02
3 = test03
4 = test04
5 = test05
二、Linux实战
1.查找有多少用户登录系统
w | awk '{print $1}' | sed 1,2d | sort | uniq -c | wc -l
w命令显示目前登入系统的用户信息,$1为用户名
awk '{print $1}'打印第一列用户名信息
sed 1,2d 删除1,2行title(1,2行不是用户信息)
sort 用sort排序
uniq -c 得到重复次数(筛选出重复登录的用户)
wc -l 显示行数,得到登录系统实际人数
2.找出所有404和500的错误日志,统计错误日志的行数
awk '$9~/404|500/{print $9}' test.log |wc -l
# test.log里每行按空格分割,$9是code字段,$9~/404|500/会在$9查405或500的都匹配出来
3.找出状态码为500错误的那条日志记录的前一行与后两行
less nginx.log | grep -E -B 1 -A 2 "HTTP\/1.1\" 500"
grep -B : 搜索到关键字后打印输出本行和前面行数
grep -A : 搜索到关键字后打印输出本行和后面行数
gerp -E : 正则匹配
找出访问量最高的url, 统计分析,取出top3
4.找出访问量最高的url, 统计分析,取出top3
test.log文件每行$7是url,命令如下:
awk '{print $7}' nginx.log| sort | uniq -c | sort -nr | head -3
# 用uniq -c 得到重复次数
#再用sort实现按次数倒叙排列
#head -3 得到出现频率最高的前三个url
5.找出 url为/topics 的平均响应时间,响应时间在倒数第二个字段
nginx.log里$7为url的位置,命令如下:
less nginx.log | awk '$7=="/topics"{total+=$(NF-1);count+=1}END{print total/count}'
6.找出访问量最高的页面地址,借助于sed的统计分析
其余规则:
- /topics/16689/replies/124751/edit 把数字替换为 /topics/id/replies/id/edit
- /_img/uploads/photo/2018/c54755ee-6bfd-489a-8a39-81a1d7551cbd.png!large 变成 /_img/uploads/photo/2018/id.png!large
- /topics/9497 改成 /topics/id
- url中的query可以去掉
输出要求如下:
url pattern对应的请求数量
取出top 10请求量的url pattern
命令:
awk '{print $7}' nginx.log |
sed -E \
-e 's#/[0-9]*/[a-z0-9\-]*\.(png|gif|jpeg|jpg).*#/_id_/_id_.image#' \
-e 's#[\?!].*##' \
-e 's#/(topics|replies|avatar)/[0-9]{1,}#/\1/_id_#g' \
-e 's#/[^/]*/(topics|followers|following|favorites|replies|columns|reward|calendar|people)#/_uid_/\1#' \
-e 's#^/[^/]*$#/_top_#' \
-e 's#/topics/node[0-9]*#/topics/node#' |
sort | uniq -c | sort -nr
7.性能统计脚本
统计阿里云盾 AliYunDun 进程的cpu与mem,持续统计20s,每秒输出一下即时的cpu与mem的利用率,并在最后结束时候给出cpu与mem的平均值,输出结果的字段用tab隔开
top -b -d 1 -n 20 | grep --line-buffered -i aliyundun$ | awk 'BEGIN{OFS="\t";print "CPU", "MEM"}{cpu=$(NF-3);mem=$(NF-2);print cpu,mem;cpu_total+=cpu;mem_total+=mem;}END{print "\navg:" ;print cpu_total/NR, mem_total/NR}'
# -d 1表示每1s更新一次
# -b:以批次的方式执行top
# -n:与-b配合使用,表示需要进行几次top命令的输出结果;-n 20就是持续进行20次;
也可以用pid的方式:
top -b -p 2076 -n 20 -d 1 | grep 2076 --line-buffered | awk 'BEGIN{print "CPU%","MEM%"}{print $9,$10}{cpu+=$9;mem+=$10}END{print "------";print cpu/NR,mem/NR}'
#pid 为2076
8.网络连接数统计
统计每个端口对应的网络连接数,以及每个端口的不同状态的数量
netstat -tnp |sed 1,2d | awk '{print $4,$6}' | awk -F: '{print $2}' | sort | uniq -c | sort -nr
# netstat -tnp前面有2行不是网络数据,所以后面用sed 1,2d删除;
# $4为链接的ip:port,$6为状态,用awk '{print $4,$6}'取出
# 用冒号:分隔取出端口号和状态 awk -F: '{print $2}'
# 最后再通过排序去重,再倒序查看
输出如下:

本文档详述了Linux进阶知识,包括wc命令、输入/输出重定向、文件描述符、lsof命令的使用,以及BRE和ERE正则表达式。此外,还介绍了如何在Linux环境中进行实战操作,如查找用户登录、错误日志分析、URL统计等,旨在提升Linux操作技能。
1550

被折叠的 条评论
为什么被折叠?



