0.前言
上篇文章介绍了systemtap probe的语法,event事件的类型,statament的常见语法。是时候利用它解决一些问题了。在此之前还得简单介绍下systemtap 内置function。
函数名称 | 用途 |
execname() | 进程名 |
pid() | pid |
tid() | 线程id |
uid() | 用户 |
cpu() | Cpu数 |
gettimeofday_s() | 系统时间.秒 UNIX epoch (January 1, 1970) |
案例一:
同事用rm –rf *删除文件后,发现磁盘空间未释放。原因在于内核正在占用该文件,rm只是删除文件在文件系统中的映射关系。正确的做法是找出并kill占用该文件的进程,如何找到该进程。可以有如下方式:
1. fuser 方式
fuser命令显示正在使用文件,目录的进程信息。
# fuser filename
(对于案例一,不能用,因为文件被删除后,会报错找不到该文件)
2 . lsof 方式
lsof |grep install.log
vi 4351 root 4u REG 253,0 65536 1461844 /root/.install.log.sw
3.利用systemtap
要在磁盘上定位一个文件,则需要所在磁盘主次设备号、inode信息。
3.1 查看设备主次号:
ls -l /dev/vda1
brw-rw----. 1 root disk 253, 0 May 7 09:56 /dev/vda1
3.2 查看文件inode
ls -il install.log
(同样的,文件被删除后,也会报错,可以用lsof)
3.3 定义systemtap脚本
vi findit.stp
probe begin
{
printf("watch inode %d %d %ld begin\n",$1,$2,$3)
}
probe vfs.write,vfs.read
{
if (dev == MKDEV($1,$2) # major/minor device
&& ino == $3)
printf ("%s(%d) %s 0x%x/%u\n",execname(), pid(), probefunc(), dev, ino)
}
3.4 执行
# stap findit.stp 253 0 1461844
watch inode 253 0 1461844 begin
3.5 另起终端执行:
# vi install.log
3.6 Systemtap输出
watch inode 253 0 1461844 begin
vi(6742) vfs_read 0xfd00000/1461844n
vi(6742) vfs_read 0xfd00000/1461844n
通过输出很容易判断是那个进程对文件作了什么操作。
4. 参考资料
http://blog.chinaunix.net/uid-24774106-id-3512909.html
https://sourceware.org/systemtap/SystemTap_Beginners_Guide/systemtapscript-handler.html