我可以运行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),有点从来没有过记录在案因为它不能正常工作。
相关链接:
只看到成功的系统调用
世界标准时间 2002 年 11 月 2 日星期六 23:07:23
使用 strace 时,我有时喜欢查看有效的系统调用(而不是所有系统调用)。
我已经移植这个补丁很多年了,它看起来非常有用。
使用 -z 选项,您不会看到不存在的文件的打开情况(对于跟踪程序实际执行的操作非常有用,而不是尝试执行)。
https://lists.strace.io/pipermail/strace-devel/2002-November/000232.html
strace:-z 选项无法正常工作
日期: 世界标准时间 2003 年 1 月 12 日星期日 09:33:01
仅跟踪失败的系统调用
创建时间:2004-03-19
[strace-4.15] 提案:-z 选项的输出暂存(仅打印成功的系统调用)/包含补丁
世界标准时间 2017 年 1 月 17 日星期二 09:35:54
https://lists.strace.io/pipermail/strace-devel/2017-January/005941.html
[PATCH v1] 为失败/成功的系统调用实现了输出分级
世界标准时间 2017 年 1 月 18 日星期三 16:01:20
https://lists.strace.io/pipermail/strace-devel/2017-January/005950.html
修复 -z 选项
2018 年 2 月 28 日
[PATCH 0/3] -z 和新 -Z 选项的阶段输出
世界标准时间 2019 年 4 月 1 日星期一 21:13:02
https://lists.strace.io/pipermail/strace-devel/2019-4月/008706.html
strace -z 标志
世界标准时间 2019 年 6 月 10 日星期一 05:29:19
https://lists.strace.io/pipermail/strace-devel/2019-June/008808.html
答案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