相信有些小伙伴有过软件压力测试的经历。我们做压力测试时为了追求性能极致,会要求得将服务器的某个或某些性能指标跑满:
比如网卡跑满了,那么网卡就是软件的性能瓶颈,要想性能更好,得提带宽;
linux如何监控网卡流量,我这里给出一个常用的命令:
sar -n DEV x,这个命令是动态监控网卡的流量情况,其中x表示每隔多久打印一次各网卡的流量信息,如sar -n DEV 2。
如果cpu跑满了,那么cpu就是制约软件性能得瓶颈,我们得看是不是cpu核数太少了,还是服务器上跑的应用太多了,占用了cpu资源,结合实际情况如资金情况、扩容成本等来考虑要不要扩容;
看cpu指标,我们一般用top命令查看,我们重点关注cpu信息的话,可以在执行top命令后,再执行shift+c,表示对cpu指标列按占用情况进行降序。
如果是磁盘跑满了,那么磁盘就是制约性能的因素。
现在我想重点写下磁盘资源的占用情况怎么看,如果知道了某个文件系统的磁盘占用率过高,那么我们又该怎么确定该文件系统下到底是哪个目录或者文件占用了主要的磁盘空间。
首先我们查看下linux文件系统磁盘的占用情况,查看文件系统磁盘的占用情况我们常用df命令,那我们先来看看df命令该怎么用、我使用的一些常用参数是什么以及这些参数的含义
df命令参数
它的用法是:df [可选参数] [文件]
-B Byte,用于指定block-size的值,计算结果为该文件系统的总占用空间/block-size,显示得是占用得磁盘块数,如1024B等于1k,那么计算的块大小就是1k,总占用空间/1k得到总的磁盘占用块数,这是磁盘占用情况的反映形式之一。
-B参数的作用
-a 表示把虚拟文件系统的磁盘占用情况也显示出来。
-h 表示以人们通俗易懂的方式显示,如以k/M/g为单位进行显示,而不是以Byte为单位。
-H 表示做换算时不是以1024来进行换算而是近似地以1000进行换算。
-i 列出文件系统的inode使用率。
注:Inodes表示文件系统的inode数量;IUsed表示已使用的inode数量;IFree表示空闲的inode数量;IUse%表示inode的使用率。
查看文件系统的inode使用率
-k 表示默认指定block-szie的值为1k。
-l 表示只显示本地文件系统的磁盘占用信息。
如df -hl,以高可读性的方式显示本次文件系统磁盘占用情况;
显示本地文件系统的磁盘占用情况
从上图中我们可以看到,/dev/sda2这个磁盘分区的占用情况比较大,达到43%了,那到底是什么占用了43%的空间呢?这个能知道吗?要怎么查看?
答案是可以的。
我们可以看到/dev/sda2这个磁盘分区的挂载点(Mounted on)是根目录/,那么我们就切换到根目录,查看下根目录下占用磁盘空间最大的那几个目录(或文件)是什么,然后再针对找出的那几个目录进行进一步的分析,以最终确定占用了大量磁盘资源的文件。
那我们如何查看linux目录占用的磁盘空间大小呢?又怎么找出占用最多的那几个目录呢?
1、linux查看目录占用磁盘空间的大小一般使用du命令,它的用法为:du [可选参数] [文件]
我使用du命令常用的几个参数有:
-h 表示以人们通俗易懂的方式显示,如以k/M/g为单位进行显示,而不是以Byte为单位。
-s 表示只显示该目录占用磁盘空间的总大小。
--max-depth=x 表示显示目录的最大深度,其中x表示最大深度。
-m 以M为单位进行显示。
-k 以k为单位进行显示。
注意:没有-g参数,即没有以g为单位显示的参数。
如:du -h --max-depth=1 ./
表示显示当前目录的占用磁盘空间的大小以及它的下一级子目录占用的磁盘空间的大小,因为--max-depth的值为,所以当前目录向下的最大深度为1。
衔接上面说的那个问题,我们知道了该怎么查看目录占用的磁盘空间后,现在要做的就是找出占用磁盘空间最大的那几个目录:
du -h -m --max-depth=1 ./ | sort -nr
查找占用当前目录下占用磁盘空间最大的那几个目录
解析以下这个命令:
使用du查看目录占用磁盘空间的大小,-h表示以人们易读的方式显示,-m表示以M为单位显示,--max-depth=1表示除了显示当前目录占用磁盘空间的大小之外,还显示当前目录所有的下一级目录的磁盘占用情况,sort -nr表示对第一列的数值(即磁盘空间占用情况)进行降序排序,-n表示进行数值比较,-r表示进行降序排序,因为有排序比较,所以前面我使用了-m来统一单位。
我们找到的占用磁盘空间最大的前几个目录是jmeter、test123以及software,其中jmeter的空间占用远远大于test123和software,所以说明占据大头的就是jmeter了,所以我们就需要接着分析jmeter目录下又是什么占据了主要空间的,到这里是不是有了一个较完整的思路了,我们就是这样一层一层地抽丝剥茧,直到最终定位到占据主要磁盘空间的源头数据在哪。
我们依然是用刚才的方法了,先切换到jmeter目录,然后执行:
du -h -m --max-depth=2 ./ | sort -nr
这里我设置了最大显示深度为2了,这个看自己的实际情况来定,如果目录树不是很深、目录数不是很多的话,可以设置大点。
继续查找jmeter目录下占据最多磁盘空间的目录
这里我们可以看到占用最多的是./apache-jmeter-5.2.1/bin目录,占了46G,整个jmeter目录才占用了47G左右。
那我们就按刚才的思路,继续追踪下去,切花到./apache-jmeter-5.2.1/bin,执行:
du -h -m --max-depth=2 ./ | sort -nr
这样一步步地最终就可以找到到底是哪个文件占用最多磁盘空间的了。
但是我这里有个现象挺有意思的,刚刚我们查找了./apache-jmeter-5.2.1/bin目录占用磁盘空间最多,但是如下图所示,你可以发现,bin目录的磁盘占用大小为46G,而其各子目录之和才16M,这也相差太多了吧,这几十G的占用情况到哪去了?被谁偷了?
bin目录下磁盘占用大小与其子目录的占用大小相距甚远
请教有经验的同事后我才明白:
linux文件系统中,当一个文件(linux万物皆文件)没有被任何进程打开(读写),那么当使用rm操作删除文件时,该文件将直接被彻底删除;
但是如果在执行rm操作删除某个文件时,该文件正在被某些进程打开了,那么该rm操作其实并不是彻底删除了文件,此时该文件处于标记删除状态(通过deleted进行标记),linux只是删除了删除了指向文件inode的链接,但是实际上数据并没有被真正删除,具体表现为:你查找不到该文件节点,但是该文件依然占用着原先的磁盘资源。
虽然文件并没有真正被删除,但是由于该文件链接不存在了,所以du工具在统计时就跳过了该文件的磁盘占用统计,所以就出现了上图所示的46G与16M的巨大差异。
有人可能有疑问了,那这个占用的磁盘资源是不是永远释放不了了?不会的,我们上面不是说过吗?该文件被某个或某些进程占用着,我们找到这些占用该文件的进程,将它们kill掉后,文件就会被真正删除了。
那我们如何查找一个文件被哪些进程占用着呢?我们使用lsof命令来查看,lsof(list open files)命令的作用是列出被打开的文件,即列出那些正被进程读写的文件的信息
lsof命令列举的每列的含义解析
COMMAND 进程名
PID 进程id
USER 哪个用户下启动的进程
FD 文件描述符
TYPE 文件类型
NODE 文件在文件系统目录树的节点编号
NAME 被打开的文件的名称
如果一个被进程占用着的文件被删除了,那么lsof得到的记录中末尾处会被打上标记(deleted),表示该文件只是被标记删除了,但未尚未真正删除,如下图:
被进程占用着的文件被删除后会被打上deleted标签
可以在root执行如下命令来找到我们想要查找的标记删除文件:
lsof | grep deleted | grep "apache-jmeter-5.2.1/bin"
找到是哪些进程打开的文件后,如果我们想要立即释放磁盘资源,那么我们可以将找到的各个进程kill掉,通过kill pid杀掉进程,然后文件就会被真正删除了,之前占用的磁盘资源就会被释放了。
换个角度想一下,如果我们不是想要释放磁盘资源,而是我们误删了某个重要文件,此时是不是会来一句卧槽,怎么办?这么重要的数据被误删了?
此时上面的问题是不是也可能会成为一种解决问题的思路:
1、我们可以先在root下执行lsof | grep deleted | grep filename
看能不能找到这个被误删了但却处于标记删除阶段的文件,如果可以找到的话,那我们还是有机会恢复的;
恢复方法,请参考:https://segmentfault.com/a/1190000000461077
2、如果没有的话,我暂时也没辙了。
网友评论