我想以有效的方式记录进程在其生命周期内所做的所有文件访问。
目前,我们通过使用 LD_PRELOAD 通过预加载拦截处理文件访问的C库调用的共享库来实现此目的。该方法在没有太多性能开销的情况下是有效的,但不是防漏的。
例如,我们的 LD_PRELOAD 共享库有一个 dlopen 的钩子。此挂钩用于跟踪对共享库的访问,但该机制无法记录共享库的三级依赖关系。
我们确实尝试使用 strace ,但使用 strace 的性能开销对我们来说并不是一个启动器。我很好奇,如果我们有其他机制,我们可以探索拦截进程及其子进程以有效方式进行的文件访问。我愿意在内核级别探索选项,挂钩到VFS层或其他任何东西。
思想?
答案 0 :(得分:3)
我们确实尝试过使用strace,但使用strace的性能开销对我们来说并非启动。
strace
速度很慢,因为它使用古老和慢ptrace
系统调用类似于应用程序的调试器。应用程序生成的每个系统调用都将被转换为信号到strace,通过strace围绕两个ptrace系统调用(也有一些打印,访问其他进程内存以获取字符串/结构值)并继续目标应用程序(2个上下文切换)。 strace
支持系统调用过滤器,但无法为ptrace注册过滤器,strace在用户空间中进行过滤,跟踪所有系统调用。
有更快的基于内核的解决方案,Brendan Gregg({3}}的作者 - Solaris,OSX,FreeBSD)有许多跟踪工具的概述(在他的Dtrace Book中:{{3 }},blog,tracing 15 minutes,BPF superpowers,60s of linux perf),例如
Choosing Tracer 2015 (with Magic pony)
您对此图的左侧部分感兴趣,靠近VFS块。 perf
(标准工具),dtrace
(仅在某些Linux中受支持,有许可证问题 - 与GPL不兼容的CDDL),stap
(page cache stats,对于像Linux这样的红色Linux更好用CentOS的)。
直接替换strace - (需要额外的内核模块,systemtap),它适用于系统调用,如tcpdump,适用于网络接口嗅探。这个工具在没有额外的上下文切换或信号的情况下嗅探内核中的系统调用,或者使用ptrace(内核已经从用户复制了所有字符串)进入其他进程内存,它还使用智能缓冲将跟踪转储到用户空间工具中。
还有其他通用的跟踪框架/工具,如lttng(out of tree),ftrace / trace-cmd。而bcc
与eBPF是现代(4.9+)Linux内核中包含的非常强大的框架(检查sysdig tool)。 bcc和eBPF允许你编写小的(安全的)代码片段,在跟踪点附近的内核中进行一些数据聚合:
如果您的Linux内核足够新,请在VFS附近尝试Brendan的工具:opensnoop
,statsnoop
,syncsnoop
;可能还有一些文件*工具(工具支持使用-p PID
进行pid过滤,或者可以在系统范围内工作)。它们部分在http://www.brendangregg.com/Slides/SCALE2017_perf_analysis_eBPF.pdf描述并在他的github上发布:(也http://www.brendangregg.com/dtrace.html)
从Linux 4.9开始,Linux内核最终具有与DTrace类似的原始功能。 ...
opensnoop是一个窥探文件打开的程序。跟踪文件名和文件句柄以及一些进程细节。
# opensnoop -g UID PID PATH FD ARGS 100 3528 /var/ld/ld.config -1 cat /etc/passwd 100 3528 /usr/lib/libc.so.1 3 cat /etc/passwd 100 3528 /etc/passwd 3 cat /etc/passwd 100 3529 /var/ld/ld.config -1 cal 100 3529 /usr/lib/libc.so.1 3 cal
rwsnoop snoop读/写事件。这是在应用程序级别测量读取和写入 - 系统调用。
# rwsnoop UID PID CMD D BYTES FILE 0 2924 sh R 128 /etc/profile 0 2924 sh R 128 /etc/profile 0 2924 sh R 128 /etc/profile 0 2924 sh R 84 /etc/profile 0 2925 quota R 757 /etc/nsswitch.conf 0 2925 quota R 0 /etc/nsswitch.conf 0 2925 quota R 668 /etc/passwd