Linux

如何按需列印目前對文件系統的讀取和寫入?

  • July 18, 2015

我有興趣獲取有關文件系統讀取和寫入的統計資訊,特別是對 NFS 掛載的統計資訊。

我知道有很多工具,例如iostat,但是每個程序都有一些問題。nfsstat``inotifywait

由於層次結構的複雜性,我不能使用任何需要我遍歷文件系統或明確提及文件名的東西。

是否有可以按需執行以下操作的程序?

  1. 顯示讀/寫
  2. 顯示讀/寫路徑
  3. 顯示字節數量

按需,我的意思是執行時間。第 (3) 點不是強制性的。

例如,我希望能夠執行以下操作:

$ magicIOprogram
read, 512, /path/to/file1
read, 256, /path/to/file2
write, 15, /path/to/file3
write, 10562, /path/to/file4

如果有辦法使用我不知道的上述工具來獲取這些資訊,那也是一個合適的解決方案。

Linux 的auditd可以獲取第 1 點和第 2 點的資訊。

假設您正在執行 RHEL/CentOS 6 並且將 nfs 共享掛載​​為/mnt/nfs/foo

$ tree /mnt/nfs/foo
/mnt/nfs/foo
|-- a
|   `-- foo
|-- b
   `-- bar

您將需要在 中定義以下規則/etc/audit/audit.rules

# Delete existing rules
-D
# Set buffer size
-b 320
# Log read and write operations
-w /mnt/nfs/foo -p r -k read -k nfs
-w /mnt/nfs/foo -p w -k write -k nfs

然後重新載入auditd服務/etc/init.d/auditd reload

完成後,您可以使用ausearchaureport讀取由以下各項生成的事件日誌auditd

$ cat /mnt/nfs/foo/a/foo
$ echo 'test' > /mnt/nfs/foo/b/bar
$ ausearch -k nfs | aureport -f
File Report
===============================================
# date time file syscall success exe auid event
===============================================
1. 07/15/2015 11:39:04 /mnt/nfs/foo/a/foo 2 yes /bin/cat 500 59
2. 07/15/2015 11:39:05 /mnt/nfs/foo/b/bar 2 yes /bin/bash 500 60

需要注意的是,它只能從客戶端收集資訊。如果您的客戶端不受信任,則無法使用此方法安全地確定他們通過 nfs 訪問的內容。

您可能想嘗試systemtap

這是一個稍加修改的範例,顯示每 100 毫秒打開、讀取和寫入:

#! /usr/bin/env stap

global fileread, filewrite

probe syscall.open.return {
   if ($return != -1) {
       printf("open, %s, %d/%d\n", user_string($filename), pid(), $return)
   }
}

probe syscall.read.return {
   p = pid()
   fd = $fd
   bytes = $return
   if (bytes > 0)
       fileread[p, fd] += bytes
}

probe syscall.write.return {
   p = pid()
   fd = $fd
   bytes = $return
   if (bytes > 0)
       filewrite[p, fd] += bytes
}

probe timer.ms(100) {
   foreach (v = [p,fd] in fileread) {
       printf("read, %d, %d/%d\n", v, p, fd)
   }                                                                                                                                                                                          
   delete fileread                                                                                                                                                                            
   foreach (v = [p,fd] in filewrite) {                                                                                                                                                        
       printf("write, %d, %d/%d\n", v, p, fd)                                                                                                                                                 
   }                                                                                                                                                                                          
   delete filewrite                                                                                                                                                                           
}

輸出行的格式為:

  • 打開,(路徑名),(pid)/(fd)
  • 讀取,(字節),(pid)/(fd)
  • 寫,(字節),(pid)/(fd)

引用自:https://unix.stackexchange.com/questions/215652