某次项目发布过程中,当我们把 rpm 包下发到每台 nc 之后,发现过了一会儿文件就被删除了,当时百思不得其解,第二天亲自试了下,果然能够稳定复现。

试了几次发现,放在 /tmp 目录下的文件,只要文件权限是当前的帐号(假设 abc),并且最近修改时间比较久(大概是分钟级别),就会被自动清理。所以第一个线索:自动清理的脚本应该是 abc 权限运行的,而且根据修改时间去删除文件。

当时第一反应是 tmpwatch 搞得鬼,但是 tmpwatch 印象中是按天执行的,而且是删除 10 天内未修改的文件(ctime/mtime/atime),所以应该可以排除。当然不排除有人擅自修改了配置文件,看了下确实不是:

flags=-umc
/usr/sbin/tmpwatch "$flags" -x /tmp/.X11-unix -x /tmp/.XIM-unix \
	-x /tmp/.font-unix -x /tmp/.ICE-unix -x /tmp/.Test-unix \
	-X '/tmp/hsperfdata_*' 240 /tmp
/usr/sbin/tmpwatch "$flags" 720 /var/tmp
for d in /var/{cache/man,catman}/{cat?,X11R6/cat?,local/cat?}; do
    if [ -d "$d" ]; then
	/usr/sbin/tmpwatch "$flags" -f 720 "$d"
    fi
done

当确认不是 tmpwatch 的问题之后,我就想找个工具去监控“删除”这个行为,google 找到 inotify-tools 工具,尝试运行采集了一把:

$inotifywatch -v -t 60 -r /tmp/b.rpm.bak
Establishing watches...
Setting up watch(es) on /tmp/b.rpm.bak
OK, /tmp/b.rpm.bak is now being watched.
Total of 1 watches.
Finished establishing watches, now collecting statistics.
Will listen for events for 60 seconds.
total  attrib  delete_self  filename
3      1       1            /tmp/b.rpm.bak

但是很遗憾,这个工具无法知道是哪个进程操作的,只能确定确实发生了“删除”的行为。

既然工具不行,就开始想找找系统日志,Linux 有日志审计(audit)的功能,只不过服务器上不一定开启,开启看看是否可以抓到问题:

$sudo /etc/init.d/auditd start
$sudo /sbin/auditctl -w /tmp/test.rpm

运行一会后,可以使用 ausearch 命令查找审计日志:

$sudo ausearch -f /tmp/test.rpm
----
time->Thu Nov 20 16:23:15 2014
type=PATH msg=audit(1416471795.984:3893): item=1 name="/tmp/b.rpm.bak" inode=8304 dev=08:02 mode=0100664 ouid=505 ogid=505 rdev=00:00
type=PATH msg=audit(1416471795.984:3893): item=0 name="/tmp/" inode=8193 dev=08:02 mode=041777 ouid=0 ogid=0 rdev=00:00
type=CWD msg=audit(1416471795.984:3893):  cwd="/"
type=SYSCALL msg=audit(1416471795.984:3893): arch=c000003e syscall=87 success=yes exit=0 a0=7ffffd607bb5 a1=7ffffd607bb5 a2=2 a3=1 items=2 ppid=16473 pid=16475 auid=0 uid=505 gid=505 euid=505 suid=505 fsuid=505 egid=505 sgid=505 fsgid=505 tty=(none) ses=154149 comm="rm" exe="/bin/rm" key=(null)

审计日志中可以看到第二个线索:删除是通过 rm 命令操作的,而且发现了进程的 pid 和 ppid。但是很遗憾,对应的进程通过 ps 命令已经找不到了,说明不是常驻进程搞得鬼。得出第三个最宝贵的线索:是一个定时执行的脚本清理了 /tmp 目录下的文件

查看全文