相信有些小伙伴有過軟件壓力測試的經歷。我們做壓力測試時為了追求性能極致,會要求得將服務器的某個或某些性能指標跑滿:
比如網卡跑滿了,那么網卡就是軟件的性能瓶頸,要想性能更好,得提帶寬;
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 [可選參數] [文件]
-B Byte,用于指定block-size的值,計算結果為該文件系統的總占用空間/block-size,顯示得是占用得磁盤塊數,如1024B等于1k,那么計算的塊大小就是1k,總占用空間/1k得到總的磁盤占用塊數,這是磁盤占用情況的反映形式之一。
-a 表示把虛擬文件系統的磁盤占用情況也顯示出來。
-h 表示以人們通俗易懂的方式顯示,如以k/M/g為單位進行顯示,而不是以Byte為單位。
-H 表示做換算時不是以1024來進行換算而是近似地以1000進行換算。
-i 列出文件系統的inode使用率。
注:Inodes表示文件系統的inode數量;IUsed表示已使用的inode數量;IFree表示空閑的inode數量;IUse%表示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了,這個看自己的實際情況來定,如果目錄樹不是很深、目錄數不是很多的話,可以設置大點。
這里我們可以看到占用最多的是./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的占用情況到哪去了?被誰偷了?
請教有經驗的同事后我才明白:
linux文件系統中,當一個文件(linux萬物皆文件)沒有被任何進程打開(讀寫),那么當使用rm操作刪除文件時,該文件將直接被徹底刪除;
但是如果在執行rm操作刪除某個文件時,該文件正在被某些進程打開了,那么該rm操作其實并不是徹底刪除了文件,此時該文件處于標記刪除狀態(通過deleted進行標記),linux只是刪除了刪除了指向文件inode的鏈接,但是實際上數據并沒有被真正刪除,具體表現為:你查找不到該文件節點,但是該文件依然占用著原先的磁盤資源。
雖然文件并沒有真正被刪除,但是由于該文件鏈接不存在了,所以du工具在統計時就跳過了該文件的磁盤占用統計,所以就出現了上圖所示的46G與16M的巨大差異。
有人可能有疑問了,那這個占用的磁盤資源是不是永遠釋放不了了?不會的,我們上面不是說過嗎?該文件被某個或某些進程占用著,我們找到這些占用該文件的進程,將它們kill掉后,文件就會被真正刪除了。
那我們如何查找一個文件被哪些進程占用著呢?我們使用lsof命令來查看,lsof(list open files)命令的作用是列出被打開的文件,即列出那些正被進程讀寫的文件的信息
COMMAND 進程名
PID 進程id
USER 哪個用戶下啟動的進程
FD 文件描述符
TYPE 文件類型
NODE 文件在文件系統目錄樹的節點編號
NAME 被打開的文件的名稱
如果一個被進程占用著的文件被刪除了,那么lsof得到的記錄中末尾處會被打上標記(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、如果沒有的話,我暫時也沒轍了。