3

我想开发一个像这样工作的命令行程序:

我的程序 /c [some_executable_here]

它启动了用户指定的命令并“监视”进程(和任何子进程)以进行读取 I/O,当该程序退出时,打印“读取”的文件列表(最终导致 read()系统调用)。

我最初的实施操作系统是 Windows,但我也想在 Linux 上做同样的事情。

到目前为止,我看到的所有类似 FileSystem 的 API 都是针对监视目录(或单个文件)而不是进程,所以我不确定最好的方法是什么。

编辑:我正在寻找如何最终实现此功能的代码示例(或至少指向我可以遵循的 API 的指针)以在 Windows 和 Linux 上执行此操作。

同样要明确的是,它不能使用诸如 OpendFilesView、procmon 或来自某些系统级工具的 grepping 字符串之类的方法,这些工具无法从执行的开始和结束通过 ID(和任何子进程)明确识别进程; IOW 通过搜索“foo.exe”并得到错误的结果,不会涉及任何时间问题和误报的可能性。

4

3 回答 3

7

在 Linux 上,我肯定会使用strace-- 它简单而强大。例如:

$ strace -o/tmp/blah -f -eopen,read bash -c "cat ciao.txt"

运行请求的命令(包括它产生的子进程,由于-f)并留下/tmp/blah(在我的例子中为 120 行)详细说明这些进程进行的所有打开和读取调用及其结果。

之后您确实需要进行一些处理,以根据需要仅提取成功读取的文件集;例如,使用 Python,您可以执行以下操作:

import re

linere = re.compile(r'^(\d+)\s+(\w+)\(([^)]+)\)\s+\=\s*(.*)$')

def main():
  openfiles = dict()
  filesread = set()
  with open('/tmp/blah') as f:
    for line in f:
      mo = linere.match(line)
      if mo is None:
        print "Unmatched line %r" % line
      pid, command, args, results = mo.groups()
      if command == 'open':
        fn = args.split(',', 1)[0].strip('"')
        fd = results.split(' ', 1)[0]
        openfiles[fd] = fn
      elif command == 'read':
        if results != '0':
          fd = args.split(',', 1)[0]
          filesread.add(openfiles[fd])
      else:
        print "Unknown command %r" % command
  print sorted(filesread)

这有点过于简单了(您需要查看其他一些系统调用,例如dup&c),但我希望能说明所需工作的要点。在我的示例中,这会发出:

['/lib/libc.so.6', '/lib/libdl.so.2', '/lib/libncurses.so.5',
 '/proc/meminfo', '/proc/sys/kernel/ngroups_max',
 '/usr/share/locale/locale.alias', 'ciao.txt']

所以它也算作“读取”那些为获取动态库而完成的操作,而不仅仅是“数据文件”......在系统调用级别,几乎没有什么区别。我想你可以过滤掉非数据文件,如果你需要的话。

我发现strace这样的目的非常方便,如果我被要求在 Windows 上做同样的工作,我的第一次尝试是选择StraceNT——不是 100% 兼容的,当然底层的系统调用名称 &c 不同,但我想我可以解释我的 Python 代码中的这些差异(准备和执行strace命令,以及对结果进行后处理)。

不幸的是,据我所知,其他一些 Unix 系统仅在您是 root (超级用户)时才提供这种功能 - 例如,在 Mac OS X 上,您需要通过sudo才能执行诸如dtracedtruss;之类的跟踪实用程序。我不知道straceMac 的直接端口,也不知道没有 root 权限执行此类任务的其他方法。

于 2009-09-27T18:47:06.343 回答
5

试试“进程监视器”(procmon.exe)它允许指定一个过滤器(要监视的进程的名称)。然后它将列出所有文件和对所述文件的操作。

在 Linux 上,尝试lsof获取当前快照并strace进行持续监控。您必须使用 过滤输出grep

所有这些工具都会检查进程结构(即操作系统用来管理进程的数据结构)并枚举其中提到的句柄/文件描述符。这不是文件系统 API 的功能,而是进程管理 API。

[编辑] 请参阅此页面上的“它是如何工作的”部分以开始在 Windows 上编写您自己的工具。

于 2009-09-17T15:41:44.850 回答
0

2014 年pv中添加了一个选项-d (--watchfd)以密切关注 pid。

易于记忆,有助于调试。

pv --help
  -d, --watchfd PID[:FD]   watch file FD opened by process PID

例如,以他的名字观看一个进程。

pv -d `pgrep firefox`
于 2018-01-12T19:47:59.643 回答