如何监测Linux进程的实时IO读写情况

运维 系统运维
怎样实时查看Linux进程的实时IO读写情况?Linux Kernel 2.6.20 以上的内核支持进程 IO 统计,可以用类似 iotop 这样的工具来监测每个进程对 IO 操作的情况。对于2.6.20以下的内核,本文提供了一个简单的Python脚本。

Linux Kernel 2.6.20 以上的内核支持进程 IO 统计,可以用类似 iotop 这样的工具来监测每个进程对 IO 操作的情况,就像用 top 来实时查看进程内存、CPU 等占用情况那样。但是对于 2.6.20 以下的 Linux 内核版本就没那么幸运了。笔者写了一个简单的 Python 脚本用来在 linux kernel < 2.6.20 下打印进程 IO 状况。

Kernel < 2.6.20

这个脚本的想法很简单,把 dmesg 的结果重定向到一个文件后再解析出来,每隔1秒钟打印一次进程 IO 读写的统计信息,执行这个脚本需要 root:

  1. #!/usr/bin/python  
  2. # Monitoring per-process disk I/O activity  
  3. # written by http://www.vpsee.com   
  4.  
  5. import sys, os, time, signal, re  
  6.  
  7. class DiskIO:  
  8.     def __init__(self, pname=None, pid=None, reads=0, writes=0):  
  9.         self.pname = pname  
  10.         self.pid = pid  
  11.         self.reads = 0 
  12.         self.writes = 0 
  13.  
  14. def main():  
  15.     argc = len(sys.argv)  
  16.     if argc != 1:  
  17.         print "usage: ./iotop" 
  18.         sys.exit(0)  
  19.  
  20.     if os.getuid() != 0:  
  21.         print "must be run as root" 
  22.         sys.exit(0)  
  23.  
  24.     signal.signal(signal.SIGINT, signal_handler)  
  25.     os.system('echo 1 > /proc/sys/vm/block_dump')  
  26.     print "TASK              PID       READ      WRITE" 
  27.     while True:  
  28.         os.system('dmesg -c > /tmp/diskio.log')  
  29.         l = []  
  30.         f = open('/tmp/diskio.log''r')  
  31.         line = f.readline()  
  32.         while line:  
  33.             m = re.match(\  
  34.                 '^(\S+)\((\d+)\): (READ|WRITE) block (\d+) on (\S+)', line)  
  35.             if m != None:  
  36.                 if not l:  
  37.                     l.append(DiskIO(m.group(1), m.group(2)))  
  38.                     line = f.readline()  
  39.                     continue 
  40.                 found = False 
  41.                 for item in l:  
  42.                     if item.pid == m.group(2):  
  43.                         found = True 
  44.                         if m.group(3) == "READ":  
  45.                             item.reads = item.reads + 1 
  46.                         elif m.group(3) == "WRITE":  
  47.                             item.writes = item.writes + 1 
  48.                 if not found:  
  49.                     l.append(DiskIO(m.group(1), m.group(2)))  
  50.             line = f.readline()  
  51.         time.sleep(1)  
  52.         for item in l:  
  53.             print "%-10s %10s %10d %10d" % \  
  54.                 (item.pname, item.pid, item.reads, item.writes)  
  55.  
  56. def signal_handler(signal, frame):  
  57.     os.system('echo 0 > /proc/sys/vm/block_dump')  
  58.     sys.exit(0)  
  59.  
  60. if __name__=="__main__":  
  61.     main()  
  62.  

Kernel >= 2.6.20

如果想用 iotop 来实时查看进程 IO 活动状况的话,需要下载和升级新内核(2.6.20 或以上版本)。编译新内核时需要打开 TASK_DELAY_ACCT 和 TASK_IO_ACCOUNTING 选项。解压内核后进入配置界面:

# tar jxvf linux-2.6.30.5.tar.bz2
# mv linux-2.6.30.5 /usr/src/
# cd /usr/src/linux-2.6.30.5

# make menuconfig

选择 Kernel hacking –> Collect scheduler debugging info 和 Collect scheduler statistics,保存内核后编译内核:

# make; make modules; make modules_install; make install

修改 grub,确认能正确启动新内核:

# vi /boot/grub/menu.lst

出了新内核外,iotop 还需要 Python 2.5 或以上才能运行,所以如果当前 Python 是 2.4 的话需要下载和安装最新的 Python 包。这里使用源代码编译安装:

# tar jxvf Python-2.6.2.tar.bz2
# cd Python-2.6.2
# ./configure
# make; make install

别忘了下载 setuptools:

# mv setuptools-0.6c9-py2.6.egg.sh setuptools-0.6c9-py2.6.egg
# sh setuptools-0.6c9-py2.6.egg

有网友对以上脚本提出问题,问到 WRITE 为什么会出现是 0 的情况,这是个好问题,笔者在这里好好解释一下。首先看看我们怎么样才能实时监测不同进程的 IO 活动状况。

block_dump

Linux 内核里提供了一个 block_dump 参数用来把 block 读写(WRITE/READ)状况 dump 到日志里,这样可以通过 dmesg 命令来查看,具体操作步骤是:

# sysctl vm.block_dump=1
or
# echo 1 > /proc/sys/vm/block_dump

然后就可以通过 dmesg 就可以观察到各个进程 IO 活动的状况了:

# dmesg -c
kjournald(542): WRITE block 222528 on dm-0
kjournald(542): WRITE block 222552 on dm-0
bash(18498): dirtied inode 5892488 (ld-linux-x86-64.so.2) on dm-0
bash(18498): dirtied inode 5892482 (ld-2.5.so) on dm-0
dmesg(18498): dirtied inode 11262038 (ld.so.cache) on dm-0
dmesg(18498): dirtied inode 5892496 (libc.so.6) on dm-0
dmesg(18498): dirtied inode 5892489 (libc-2.5.so) on dm-0

问题

一位细心的网友提到这样一个问题:为什么会有 WRITE block 0 的情况出现呢?笔者跟踪了一段时间,发现确实有 WRITE 0 的情况出现,比如:

# dmesg -c
...
pdflush(23123): WRITE block 0 on sdb1
pdflush(23123): WRITE block 16 on sdb1
pdflush(23123): WRITE block 104 on sdb1
pdflush(23123): WRITE block 40884480 on sdb1
...

答案

原来我们把 WRITE block 0,WRITE block 16, WRITE block 104 这里面包含的数字理解错了,这些数字不是代表写了多少 blocks,是代表写到哪个 block,为了寻找真相,笔者追到 Linux 2.6.18 内核代码里,在 ll_rw_blk.c 里找到了答案:

$ vi linux-2.6.18/block/ll_rw_blk.c

  1. void submit_bio(int rw, struct bio *bio)  
  2. {  
  3.         int count = bio_sectors(bio);  
  4.  
  5.         BIO_BUG_ON(!bio->bi_size);  
  6.         BIO_BUG_ON(!bio->bi_io_vec);  
  7.         bio->bi_rw |= rw;  
  8.         if (rw & WRITE)  
  9.                 count_vm_events(PGPGOUT, count);  
  10.         else 
  11.                 count_vm_events(PGPGIN, count);  
  12.  
  13.         if (unlikely(block_dump)) {  
  14.                 char b[BDEVNAME_SIZE];  
  15.                 printk(KERN_DEBUG "%s(%d): %s block %Lu on %s\n",  
  16.                         current->comm, current->pid,  
  17.                         (rw & WRITE) ? "WRITE" : "READ",  
  18.                         (unsigned long long)bio->bi_sector,  
  19.                         bdevname(bio->bi_bdev,b));  
  20.         }  
  21.  
  22.         generic_make_request(bio);  
  23. }  

很明显从上面代码可以看出 WRITE block 0 on sdb1,这里的 0 是 bio->bi_sector,是写到哪个 sector,不是 WRITE 了多少 blocks 的意思。还有,如果 block 设备被分成多个区的话,这个 bi_sector(sector number)是从这个分区开始计数,比如 block 0 on sdb1 就是 sdb1 分区上的第0个 sector 开始。

原文地址:http://www.vpsee.com/2010/07/monitoring-process-io-activity-on-linux-with-block_dump/

【编辑推荐】

  1. Linux技巧:多核下绑定硬件/进程到不同CPU
  2. 重置CentOS-root密码的简便方法
  3. Linux定时执行任务命令概述:at和crontab
责任编辑:yangsai 来源: vpsee.com
相关推荐

2011-11-08 21:51:43

Linux 监控 IO

2010-12-22 13:17:47

Linux性能监测磁盘IO

2023-08-21 14:18:48

操作系统Linux

2019-08-15 15:00:29

监测Linux性能NetData

2017-01-18 21:57:14

2010-06-02 11:06:15

Linux 内存监控

2018-08-27 11:18:01

存储

2018-11-01 10:59:52

Linux内存进程

2021-11-29 20:44:31

Linux内存进程

2015-10-13 08:59:59

合作组织实时Linux

2022-04-23 16:30:22

Linux磁盘性能

2020-12-01 08:00:00

Linux服务器系统

2015-06-25 12:41:53

实时 Node应用性能监测

2012-03-31 13:55:15

Java

2011-09-08 09:24:34

Mac Widget监测系统iStatpro

2020-04-29 15:10:16

Linux命令进程

2021-08-11 10:41:50

博睿数据IT运维

2019-06-05 09:14:28

LinuxIO监控分析

2013-11-14 10:32:40

Linux系统监测系统温度

2017-05-26 12:59:48

Linux端口
点赞
收藏

51CTO技术栈公众号