检测进程 used/modified/created/deleted 哪些文件的最佳方法是什么?
What is the best method to detect which files are used/modified/created/deleted by a process?
我想编写能够在进程(及其子进程)执行期间检测所有 used/created/modified/deleted 文件的软件。该进程尚未 运行 - 用户提供了一个命令行,稍后将通过 bash 进行子处理,因此我们可以在执行前后做一些事情,并控制环境命令是 运行中
到目前为止我想到了四种可能有用的方法:
- 解析命令行以识别提到的文件和目录。假设使用了所有明确提及的文件。检查目录 before/after 中是否有 created/deleted 个文件。 MD5 现有文件before/after 看有没有被修改。这适用于所有操作系统和环境,但显然有严重的局限性(当命令为“./script.sh”时不起作用)
- 运行 该进程通过另一个进程,如 strace(OSX 的 dtruss,并且有等效的 windows 程序),它监听系统调用。解析输出文件以查找文件 used/modified/deleted/created。优点是比MD5方法灵敏,可以处理script.sh。缺点是它非常 OS 具体(dtruss 需要 root 权限,即使进程 运行 不需要 - 工具的输出完全不同)。如果有很多 read/write 操作,也可能会创建巨大的日志文件,并且肯定会减慢速度。
- 将类似于上面的东西集成到内核中。显然仍然是 OS 特定的,但至少现在我们在发号施令,为所有 OS 创建通用输出格式。不会创建巨大的日志文件,甚至可以在进程请求第一个 read() 到文件后停止将系统调用挂钩到 read()。我认为这是 inotify 工具正在做的事情,但我一点也不熟悉它,也不熟悉内核编程!
- 运行 使用 LD_PRELOAD 技巧的过程(在 OSX 上称为 DYLD_INSERT_LIBRARIES,不确定它是否存在于 Windows 中),它基本上覆盖使用我们自己的 open() 版本的进程对 open() 的任何调用,它记录了我们正在打开的内容。写、读等也一样。它做起来非常简单,而且性能非常好,因为您实际上是在教进程记录自己。缺点是它只适用于动态链接的进程,我不知道 dynamic/statically 链接程序的流行。我什至不知道是否有可能在执行之前判断一个进程是动态链接还是静态链接(默认情况下使用此方法,但如果不可能则回退到性能较低的方法)。
我需要帮助来选择最佳的下降路径。我已经实现了第一种方法,因为它很简单,并为我提供了一种在日志记录后端 (http://ac.gt/log) 上工作的方法,但实际上我需要升级到其他方法之一。您的建议将是无价的:)
查看 "strace" 的源代码(及其 -f 以跟踪子级)。它基本上完成了您正在尝试做的事情。它捕获进程(或其子进程)的所有系统调用,因此您可以 grep 进行 "open" 等操作
下面link提供了一些使用ptrace系统调用实现自己的strace的例子:
https://blog.nelhage.com/2010/08/write-yourself-an-strace-in-70-lines-of-code/
我想编写能够在进程(及其子进程)执行期间检测所有 used/created/modified/deleted 文件的软件。该进程尚未 运行 - 用户提供了一个命令行,稍后将通过 bash 进行子处理,因此我们可以在执行前后做一些事情,并控制环境命令是 运行中
到目前为止我想到了四种可能有用的方法:
- 解析命令行以识别提到的文件和目录。假设使用了所有明确提及的文件。检查目录 before/after 中是否有 created/deleted 个文件。 MD5 现有文件before/after 看有没有被修改。这适用于所有操作系统和环境,但显然有严重的局限性(当命令为“./script.sh”时不起作用)
- 运行 该进程通过另一个进程,如 strace(OSX 的 dtruss,并且有等效的 windows 程序),它监听系统调用。解析输出文件以查找文件 used/modified/deleted/created。优点是比MD5方法灵敏,可以处理script.sh。缺点是它非常 OS 具体(dtruss 需要 root 权限,即使进程 运行 不需要 - 工具的输出完全不同)。如果有很多 read/write 操作,也可能会创建巨大的日志文件,并且肯定会减慢速度。
- 将类似于上面的东西集成到内核中。显然仍然是 OS 特定的,但至少现在我们在发号施令,为所有 OS 创建通用输出格式。不会创建巨大的日志文件,甚至可以在进程请求第一个 read() 到文件后停止将系统调用挂钩到 read()。我认为这是 inotify 工具正在做的事情,但我一点也不熟悉它,也不熟悉内核编程!
- 运行 使用 LD_PRELOAD 技巧的过程(在 OSX 上称为 DYLD_INSERT_LIBRARIES,不确定它是否存在于 Windows 中),它基本上覆盖使用我们自己的 open() 版本的进程对 open() 的任何调用,它记录了我们正在打开的内容。写、读等也一样。它做起来非常简单,而且性能非常好,因为您实际上是在教进程记录自己。缺点是它只适用于动态链接的进程,我不知道 dynamic/statically 链接程序的流行。我什至不知道是否有可能在执行之前判断一个进程是动态链接还是静态链接(默认情况下使用此方法,但如果不可能则回退到性能较低的方法)。
我需要帮助来选择最佳的下降路径。我已经实现了第一种方法,因为它很简单,并为我提供了一种在日志记录后端 (http://ac.gt/log) 上工作的方法,但实际上我需要升级到其他方法之一。您的建议将是无价的:)
查看 "strace" 的源代码(及其 -f 以跟踪子级)。它基本上完成了您正在尝试做的事情。它捕获进程(或其子进程)的所有系统调用,因此您可以 grep 进行 "open" 等操作
下面link提供了一些使用ptrace系统调用实现自己的strace的例子:
https://blog.nelhage.com/2010/08/write-yourself-an-strace-in-70-lines-of-code/