Linux 如何查看文件是被那個進程佔用寫數據?

點擊上方「藍字」關注我們

目錄

  • 背景

  • 步驟

  • 獲取寫文件的進程號


文件被那個進程使用,寫數據不是用lsof可以找出來嗎,但現實情況是lsof沒找出來T_T


背景

centos7 在某一段時間監控報警磁盤使用率達99%,由於監控屬於概要形式信息,沒有快照信息的監控(能發現某進程的I/O,CPU消耗情況),所以需要在服務器上去定時執行統計命令獲取快照信息。
需要通過iostat -dx -k去查看avgqu-sz、await、svctm、%util;
sar -u查看%iowait、%user;
pidstat -d 查看進程I/O讀寫的快照信息


步驟

  • 生成統計信息文件

cat>/tmp/at_task.sh<<EOF
pidstat -d 2 >/tmp/pidstat_\`date +%F_%T\`.log 2>& 1 &
sar -u 2  >/tmp/sar_\`date +%F_%T\`.log 2>& 1 &
while [ 1 ];do echo -n \`date +%T\` >>/tmp/iostat_\`date +%F\` 2>& 1  && iostat -dx -k 1 1 >>/tmp/iostat_\`date +%F\` 2>& 1; sleep 2; done &
EOF

在while循環中使用iostat的原因是要輸出date +%T時間,不然只有數據,沒有時間信息也沒有什麼用

  • 使用at 命令定時執行

at 15:14 today -f /tmp/at_task.sh

出現錯誤

Can't open /var/run/atd.pid to signal atd. No atd running?

重啓atd服務

service atd restart

重新開啓at定時任務

at 15:14 today -f /tmp/at_task.sh
job 2 at Wed Mar 13 15:14:00 2019

得到如下快照信息
iostat

15:13:35Linux 3.10.0-862.14.4.el7.x86_64 (ip-xxxxx)     03/13/2019      _x86_64_        (4 CPU)

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.12     0.07   17.31   19.41   580.79    90.52    36.57     0.09    2.39    4.42    0.57   0.72   2.63
scd0              0.00     0.00    0.00    0.00     0.00     0.00     6.00     0.00    0.28    0.28    0.00   0.25   0.00

sar

03:14:00 PM     CPU     %user     %nice   %system   %iowait    %steal     %idle
03:14:02 PM     all      0.25      0.00      0.38      0.00      0.00     99.37
03:14:04 PM     all      1.25      0.13      0.63      0.00      0.00     97.99
03:14:06 PM     all      0.25      0.13      0.50      0.00      0.00     99.12
03:14:08 PM     all      0.50      0.00      0.50      0.63      0.00     98.37

pidstat

03:14:00 PM   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s  Command
03:14:02 PM  5700      9089      0.00      6.00      0.00  uxxx
03:14:02 PM  5700      9140      0.00      6.00      0.00  uxxx
03:14:02 PM  5700      9292      0.00     10.00      0.00  uxxx
03:14:02 PM     0     18084      0.00      2.00      0.00  bash

kill 掉收集信息的命令

ps -ef | egrep 'iostat|sar|pidstat|while' | grep -v grep | awk '{print $2}' | xargs -l kill

但ps -ef | egrep 命令沒有獲取到while循環的pid,不kill掉該while循環,就會一直對/tmp/iostat_2019-03-13寫數據-_-

通過lsof 沒有定位到打開文件的進程

lsof /tmp/iostat_2019-03-13 
[root@ip-10-186-60-117 ~]#
[root@ip-10-186-60-117 ~]#

通過lsof 可以定位到打開mysql-error.log的進程

lsof /opt/mysql/data/5690/mysql-error.log 
COMMAND   PID                USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
mysqld  12858 actiontech-universe    1w   REG  253,1     6345 20083533 /opt/mysql/data/5690/mysql-error.log
mysqld  12858 actiontech-universe    2w   REG  253,1     6345 20083533 /opt/mysql/data/5690/mysql-error.log

可見,某進程只有一隻持有某文件的inode,纔可以通過lsof查看文件在被那些進程使用


獲取寫文件的進程號

安裝sysemtap

yum -y install systemtap

SystemTap 是對 Linux 內核監控和跟蹤的工具
利用systemtap中的inodewatch.stp工具來查找寫文件的進程號

得到文件的inode

stat -c '%i' /tmp/iostat_2019-03-13 
4210339

獲取文件所在設備的major,minor

ls -al /dev/vda1
brw-rw---- 1 root disk 253, 1 Jan 30 13:57 /dev/vda1

得到寫文件的pid

stap /usr/share/systemtap/examples/io/inodewatch.stp 253 1  4210339

Checking "/lib/modules/3.10.0-862.14.4.el7.x86_64/build/.config" failed with error: No such file or directory
Incorrect version or missing kernel-devel package, use: yum install kernel-devel-3.10.0-862.14.4.el7.x86_64

根據系統內核版本在kernel-devel rpm build for : Scientific Linux 7網站上下載相應的kernal-devel包

wget ftp://ftp.pbone.net/mirror/ftp.scientificlinux.org/linux/scientific/7.2/x86_64/updates/security/kernel-devel-3.10.0-862.14.4.el7.x86_64.rpm

rpm -ivh kernel-devel-3.10.0-862.14.4.el7.x86_64.rpm

再次執行stap

stap /usr/share/systemtap/examples/io/inodewatch.stp 253 1 4210339
......
Missing separate debuginfos, use: debuginfo-install kernel-3.10.0-862.14.4.el7.x86_64
Pass 2: analysis failed. [man error::pass2]
Number of similar error messages suppressed: 2.

安裝debuginfo kernal

debuginfo-install kernel-3.10.0-862.14.4.el7.x86_64
  Verifying  : kernel-debuginfo-common-x86_64-3.10.0-862.14.4.el7.x86_64                        1/3 
  Verifying  : yum-plugin-auto-update-debug-info-1.1.31-50.el7.noarch                           2/3 
  Verifying  : kernel-debuginfo-3.10.0-862.14.4.el7.x86_64                                      3/3 

Installed:
  kernel-debuginfo.x86_64 0:3.10.0-862.14.4.el7
  yum-plugin-auto-update-debug-info.noarch 0:1.1.31-50.el7

Dependency Installed:
  kernel-debuginfo-common-x86_64.x86_64 0:3.10.0-862.14.4.el7

再次執行stap

stap /usr/share/systemtap/examples/io/inodewatch.stp 253 1  4210339
ERROR: module version mismatch (#1 SMP Tue Sep 25 14:32:52 CDT 2018 vs #1 SMP Wed Sep 26 15:12:11 UTC 2018), release 3.10.0-862.14.4.el7.x86_64
WARNING: /usr/bin/staprun exited with status: 1

添加 -v查看詳細報錯
stap -v  /usr/share/systemtap/examples/io/inodewatch.stp 253 1  4210339
Pass 1: parsed user script and 471 library scripts using 240276virt/41896res/3368shr/38600data kb, in 300usr/20sys/320real ms.
Pass 2: analyzed script: 2 probes, 12 functions, 8 embeds, 0 globals using 399436virt/196284res/4744shr/197760data kb, in 1540usr/560sys/2106real ms.
Pass 3: using cached /root/.systemtap/cache/f5/stap_f5c0cd780e8a2cac973c9e3ee69fba0c_7030.c
Pass 4: using cached /root/.systemtap/cache/f5/stap_f5c0cd780e8a2cac973c9e3ee69fba0c_7030.ko
Pass 5: starting run.
ERROR: module version mismatch (#1 SMP Tue Sep 25 14:32:52 CDT 2018 vs #1 SMP Wed Sep 26 15:12:11 UTC 2018), release 3.10.0-862.14.4.el7.x86_64
WARNING: /usr/bin/staprun exited with status: 1
Pass 5: run completed in 0usr/10sys/38real ms.
Pass 5: run failed.  [man error::pass5]

修改

vim /usr/src/kernels/3.10.0-862.14.4.el7.x86_64/include/generated/compile.h

#define UTS_VERSION "#1 SMP Tue Sep 25 14:32:52 CDT 2018"
改爲
#define UTS_VERSION "#1 SMP Wed Sep 26 15:12:11 UTC 2018"

rm -rf  /root/.systemtap/cache/f5/stap_f5c0cd780e8a2cac973c9e3ee69fba0c_7030*

再次執行

stap /usr/share/systemtap/examples/io/inodewatch.stp 253 1 4210339

iostat(4671) vfs_write 0xfd00001/4210339
iostat(4671) vfs_write 0xfd00001/4210339
iostat(4671) vfs_write 0xfd00001/4210339
iostat(4671) vfs_write 0xfd00001/4210339
iostat(4671) vfs_write 0xfd00001/4210339
iostat(4671) vfs_write 0xfd00001/4210339
iostat(4671) vfs_write 0xfd00001/4210339
iostat(4671) vfs_write 0xfd00001/4210339
iostat(4671) vfs_write 0xfd00001/4210339
iostat(4671) vfs_write 0xfd00001/4210339
iostat(4677) vfs_write 0xfd00001/4210339
iostat(4677) vfs_write 0xfd00001/4210339
iostat(4677) vfs_write 0xfd00001/4210339
iostat(4677) vfs_write 0xfd00001/4210339
iostat(4677) vfs_write 0xfd00001/4210339
iostat(4677) vfs_write 0xfd00001/4210339
iostat(4677) vfs_write 0xfd00001/4210339
iostat(4677) vfs_write 0xfd00001/4210339
iostat(4677) vfs_write 0xfd00001/4210339
iostat(4677) vfs_write 0xfd00001/4210339
iostat(4683) vfs_write 0xfd00001/4210339
............

可見已經得到了寫/tmp/iostat_date +%F 文件的進程號,但進程號一直在打印出來,因爲後臺進程iostat -dx -m 的在while循環中的,每隔sleep 2s 後就會執行一次iostat 產生新的pid。
那要怎樣才能讓iostat -dx -m 停止寫/tmp/iostat_date +%F 文件了?除了重啓大法好 $_$

rm -rf 也不能終止後臺的while iostat進程寫文件,刪除了文件後,while循環又會生成新的文件

rm -rf  /tmp/iostat_2019-03-1*

stat /tmp/iostat_2019-03-1*
  File: ‘/tmp/iostat_2019-03-13’
  Size: 146700    	Blocks: 512        IO Block: 4096   regular file
Device: fd01h/64769d	Inode: 4210339     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2019-03-14 16:07:26.211888899 +0800
Modify: 2019-03-14 16:18:17.854019793 +0800
Change: 2019-03-14 16:18:17.854019793 +0800

正確做法

cat>/tmp/iostat.sh<<EOF
while [ 1 ];do echo -n \`date +%T\` >>/tmp/iostat_\`date +%F\` 2>& 1  && iostat -dx -m 1 1 >>/tmp/iostat_\`date +%F\` 2>& 1; sleep 2; done &
EOF

at  now + 1 minute  today
bash /tmp/iostat.sh

#這樣就能方便的獲取到進程號pid了
ps -ef | grep iostat
root      8593     1  0 16:16 pts/2    00:00:00 bash /tmp/iostat.sh

http協議無狀態中的 "狀態" 到底指的是什麼?!

用Nginx實現接口慢查詢並可示化展示TOP 20

MySQL 加鎖和死鎖解析

如果是MySQL引起的CPU消耗過大,你會如何優化?

在看”的永遠18歲~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章