标题: filemonitor.stp 创建: 2016-11-15 12:37 更新: 链接: https://scz.617.cn/unix/201611151237.txt 小华说起他排查某故障时用到一名为inodewatch的工具,可以进行系统级的文件访问 监控。虽然我在Linux上从未产生过这种需求,但出于对各种调试手段的不懈追求, 还是忍不住翻查了它的相关资料。 inodewatch依赖于SystemTap,不是所有的内核缺省都支持。Linux的SystemTap相当 于Solaris的DTrace,前者是受后者启发、影响而产生的。对于Windows用户,可以简 单类比Process Monitor。 /usr/share/doc/systemtap-doc/examples/io/inodewatch.stp -------------------------------------------------------------------------- #! /usr/bin/env stap probe vfs.write, vfs.read { # dev and ino are defined by vfs.write and vfs.read if (dev == MKDEV($1,$2) # major/minor device && ino == $3) printf ("%s(%d) %s 0x%x/%u\n", execname(), pid(), ppfunc(), dev, ino) } -------------------------------------------------------------------------- 假设我们想知道谁在访问/etc/passwd。 # stat -c '%D %i' /etc/passwd 801 800055 801是16进制的0x0801,其中0x08是major device number,0x01是minor device number。 800055是inode number。 # stap /usr/share/doc/systemtap-doc/examples/io/inodewatch.stp 0x08 0x01 800055 accounts-daemon(649) vfs_read 0x800001/800055 accounts-daemon(649) vfs_read 0x800001/800055 accounts-daemon(649) vfs_read 0x800001/800055 accounts-daemon(649) vfs_read 0x800001/800055 gnome-settings-(2298) vfs_read 0x800001/800055 gnome-settings-(2298) vfs_read 0x800001/800055 前2行输出是远程SSH登录触发的,后4行输出是本地X登录触发的。 关于inodewatch.stp我得吐个槽,中文全是翻来覆去地炒冷饭。难道每次"stat -c" 获取inode号是很符合人类习性的操作?我觉得这里天然地应该直接指定被监控文件 名才是。之所以inodewatch.stp的中文例子如此之多,因为SystemTap官方文档里给 了这么一个例子,然后我朝最不缺的就是低阶搬运工。 下面是更接近人类习性的filemonitor.stp: -------------------------------------------------------------------------- #! /usr/bin/env stap probe vfs.write, vfs.read { filename = inode_path( $file->f_inode ) if ( filename == @1 ) { printf( "[%u][%s][%s][%s][%s]\n", pid(), execname(), cmdline_str(), name, filename ) } } -------------------------------------------------------------------------- # stap filemonitor.stp /etc/passwd [18314][cat][cat /etc/passwd][vfs.read][/etc/passwd] [649][accounts-daemon][/usr/lib/accountsservice/accounts-daemon][vfs.read][/etc/passwd] # stap -e 'probe vfs.write,vfs.read{filename=inode_path($file->f_inode);if(filename==@1)printf("[%u][%s][%s][%s][%s]\n",pid(),execname(),cmdline_str(),name,filename)}' /etc/passwd [19024][cat][cat /etc/passwd][vfs.read][/etc/passwd] [19025][vi][vi /etc/passwd][vfs.read][/etc/passwd] 再吐个槽,什么时候各个Linux发行版的SystemTap才能步调一致地稳定下来。Debian 8.5缺省的SystemTap版本太低了,不支持fullpath_struct_file()。这种后娘养的 SystemTap,让那些经历过DTrace的人群情何以堪。