附录

附录

我可以运行strace类似的命令sleep 1 并查看它正在访问哪些文件,如下所示:

strace -e trace=file -o strace.log sleep 1

然而,在我的机器上,许多调用的返回值为-1,表明该文件不存在。例如:

$ grep '= -1 ENOENT' strace.log | head
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en_US.UTF-8/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en_US.UTF-8/LC_MEASUREMENT", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en_US.UTF-8/LC_TELEPHONE", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en_US.UTF-8/LC_ADDRESS", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en_US.UTF-8/LC_NAME", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en_US.UTF-8/LC_PAPER", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)

我对不存在的文件并不真正感兴趣,我想知道进程实际找到并读取了哪些文件。除了 之外grep -v '=-1 ENOENT',我怎样才能可靠地过滤掉失败的呼叫?

附录

我很惊讶地发现,strace自 2002 年以来,这个功能就以标志的形式出现在作品中-z,它是 的别名-e status=successful,功能齐全从5.2版本开始2019-07-12),也可作为--successful-only 从5.6版本开始2020-04-07)。

-z自版本 5.2 起也可用,该标志是 的补充,-Z该标志是 的别名,自版本 5.6 起-e status=failed可用。--failed-only

国旗-z首次添加于 2002 年的提交中并于 4.5.18 版本发布(2008-08-28),有点从来没有过记录在案因为它不能正常工作。

相关链接:

答案1

除了对输出进行后处理之外strace,没有任何可用于忽略strace.添加起来不会太难,看一下syscall_exiting_trace里面的函数syscall.c

如果你更愿意追求后期处理的角度,奥莱·丹格已经以比您可能在这里看到的更全面的方式为您解决了这个问题:tracefile工具将以strace易于阅读的方式运行并过滤出您想要的信息。看列出程序访问的文件了解详情。另一个答案针对这个问题列出了其他可能的方法,包括记录文件系统我觉得这非常有用。

另一种选择是使用系统点击;例如

#!/usr/bin/env stap

global stored_filename, stored_path

probe syscall.open {
  stored_filename = filename
}

probe syscall.open.return {
  if (execname() == "cat" && $return >= 0) {
    printf("opened %s\n", stored_filename)
  }
}

probe syscall.openat {
  stored_filename = filename
  stored_path = dfd_str
}

probe syscall.openat.return {
  if (execname() == "cat" && $return >= 0) {
    printf("opened %s in %s\n", stored_filename, stored_path)
  }
}

将显示任何进程成功打开的任何文件的名称cat

答案2

可能的解决方案:

strace -e trace=file sleep 1 2>&1 | grep -v "= -1 ENOENT" > strace.log

strace默认情况下打印到,stderr因此将其重定向到stdout.

答案3

稍微更可靠的模式(即意外跳过错误行的风险稍微降低)可能是

| grep -v "= -1 ENOENT [(]No such file or directory[)]$"

即复制粘贴行尾,“转义”括号(否则可能被视为特殊字符),并将特殊字符添加$到将模式“锚定”到行尾的末尾。

我在 中找不到更好的选择man strace。快速而肮脏的文本操作技巧是 Unix 之道:-P。

几乎可以肯定,可以使用自定义gdb脚本来完成您想要的操作。但这是更多的工作,而且我还没有准备这样的脚本。

另一个问题引用了一个tracefile脚本,您可以使用该-e选项运行该脚本。这仍然是通过解析 的输出来实现的strace,因此它似乎也不完全可靠,但我想您可能更喜欢它。 https://gitlab.com/ole.tange/tangetools/blob/master/tracefile/tracefile

相关内容