Linux Troubleshooting 超實用系列 – Disk Analysis
- 2022 年 5 月 16 日
- 筆記
筆者歷史文章: //github.com/CarlJi/words
關於磁盤的使用,實際生產中以下問題會較為常見:
No space left on device
– 空間不足Disk utilization 100%
– 磁盤I/O過載Too many open files
– 文件句柄過多Input/output error
– 讀寫錯誤
而掌握常見的分析套路會事半功倍。
Disk usage
第一時間明確磁盤容量及使用情況總是沒錯的,這時候df -h
命令就比較方便:
$ df -h
Filesystem Size Used Avail Use% Mounted on
udev 48G 4.0K 48G 1% /dev
tmpfs 9.5G 8.55G 9.5G 90% /run
/dev/sda1 275G 234G 28G 90% /
/dev/sdd1 2.7T 1.6T 1.2T 57% /disk3
/dev/sdc1 3.6T 2.6T 1.1T 72% /disk1
/dev/sdb1 3.6T 4.2G 3.6T 1% /disk2
Use%
這個指標就比較清晰展示目標磁盤已經使用多少了。
注意,第三行的
tmpfs
文件系統比較特殊,其數據實際是存儲在內存中而非磁盤。
Inode usage
有時候我們會發現明明磁盤有容量,但是程序仍然報No space left on device
,這是因為什麼呢?
答案大概率是Inode耗盡了。這時候可以通過df -i
來確認,比如:
$ df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
udev 12370103 518 12369585 1% /dev
tmpfs 12372788 611 12372177 1% /run
/dev/sda1 18317312 1941821 16375491 11% /
/dev/sdd1 183148544 181317058 1831468 99% /disk3
/dev/sdc1 244195328 153483 244041845 1% /disk1
/dev/sdb1 244195328 7496 244187832 1% /disk2
可以看到/disk3
對應的目錄其Inode已經使用99%,很快就會耗盡。Inode代表的是文件的metadata信息,若inode使用過多,通常意味着目錄里小文件太多了。
PS: 不規範的容器化姿勢比較容易出現這個問題,比如Pod一直在產生日誌,且使用的是系統盤又不定期回收。
Disk utilization high
磁盤使用率高,一般是已經知道是哪個盤了,但如果不知道,使用iostat -x 1
也能較清晰的查看到:
$ iostat -x 1
Linux 3.19.0-80-generic 2022年05月12日 _x86_64_ (24 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
5.85 0.00 3.60 4.83 0.00 85.72
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.00 237.00 441.00 48.00 56448.00 1388.00 236.55 0.97 1.98 1.02 10.83 1.00 48.80
sdb 0.00 26.00 2.00 186.00 8.00 93876.00 998.77 44.51 348.13 466.00 346.86 5.32 100.00
sdc 0.00 0.00 155.00 7.00 18132.00 16.00 224.05 6.62 47.95 46.71 75.43 4.02 65.20
sdd 0.00 30.00 8.00 8.00 900.00 212.00 139.00 0.10 6.25 3.50 9.00 6.00 9.60
PS:
iostat -xd <device> 1
可以只查看某個設備。
可以看到sdb這塊盤,其%util
指標已經100%。
但要注意,%util
高並不嚴格意味着磁盤已經過載了,因為現代硬盤設備都有並行處理多個I/O請求的能力。要關注磁盤利用率,還需要關注await
(再具體就是讀r_await
和寫w_await
指標),這個指標大致等於單個I/O所需的平均時間,所以如果它也很大,那磁盤一定是很繁忙了。
Which processes are using the specific disk?
實際場景中,面對磁盤負載高,我們通常需要做的是找到”罪魁禍首”,判斷其行為是否符合預期。
粗略的可以通過 iotop -oP
直接查看當前正在讀寫的進程。一般機器上有哪些程序,我們應該比較清楚,所以這時候可以大致判斷出來:
$ iotop -oP
Total DISK READ : 173.26 M/s | Total DISK WRITE : 177.38 M/s
Actual DISK READ: 175.77 M/s | Actual DISK WRITE: 85.50 M/s
PID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
6929 be/4 root 168.67 M/s 168.57 M/s 0.00 % 76.51 % dd if=/dev/sda bs=4M count=100000 of=mbr.img
379 be/3 root 0.00 B/s 15.61 K/s 0.00 % 2.01 % [jbd2/sda1-8]
當然這種方式也存在一個問題,你是看不出目標進程具體使用哪塊磁盤的。那怎麼辦呢?可以藉助lsof +D <目錄>
命令,通過正在打開的文件句柄來識別進程:
$ lsof +D /disk2
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
prometheu 1705 root mem REG 8,17 72567556 234356807 /disk2/prometheus_dir/data/01G2J2YMJPY9HXMP5KSPW30MM1/chunks/000001
prometheu 1705 root mem REG 8,17 73620431 234356815 /disk2/prometheus_dir/data/01G19H692F7JN796CBQDSFVV1W/chunks/000001
prometheu 1705 root mem REG 8,17 73173252 234356814 /disk2/prometheus_dir/data/01G13QSNA21PYK2R6SC0BFYZYM/chunks/000001
然後通過pidstat -d
進一步分析這些進程的讀寫情況 :
$ pidstat -d
Linux 3.19.0-80-generic 2022年05月15日 _x86_64_(24 CPU)
16時21分37秒 UID PID kB_rd/s kB_wr/s kB_ccwr/s Command
16時21分59秒 0 1705 64.00 67.19 0.00 prometheus
kB_rd/s
和 kB_wr/s
這兩個指標,能基本代表進程讀寫磁盤的速度。
Too many open files
相信後端同學大多都遇到過Too may open files
的錯誤,因為高並發場景下,服務會建立很多連接,這時候就會很容易遇到這個錯誤。
可以通過ls -1 /proc/<pid>/fd | wc -l
命令來查看當前進程已經打開了多少個文件:
$ ls -1 /proc/1705/fd | wc -l
1258
而若想查看某進程具體的句柄限制,可以通過命令cat /proc/<pid>/limits
:
$ cat /proc/1705/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 386565 386565 processes
Max open files 20240 20240 files
而若要調整這個限制,可以通過ulimit
命令或修改系統文件/etc/security/limits.conf
.
EIO (input/output error)
遇到這個錯誤,一般是物理磁盤壞了。可能是整個盤壞了不能讀寫,也有可能是某個block有問題。這時候通過dmesg -T
查看內核日誌,通常會有相應的error信息。
參考資料
- //linuxperf.com/?p=156
- //linuxperf.com/?p=40
- //man7.org/linux/man-pages/man1/pidstat.1.html
- //engineering.saltside.se/linux-troubleshooting-disk-analysis-2dc40c6c49b4