目录
背景
步骤
获取写文件的进程号
文件被那个进程使用, 写数据不是用 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*
参考 SystemTap - 安装
再次执行
- 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
参考
I Need the Kernel Source
Linux 下如何知道文件被那个进程写 http://blog.sae.sina.com.cn/archives/881
Linux 下的 IO 监控与分析
使用 systemtap 调查异常 io 的来源
来源: https://www.cnblogs.com/YangJiaXin/p/10531197.html