这类似于例如这,但不完全是;我将 strace 的输出保存到文件中,如下所示:
...
3691 fcntl(2, F_GETFD) = 0
3691 access("/etc/suid-debug", F_OK) = -1 ENOENT (No such file or directory)
3691 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
3691 openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
3691 fstat(3, {st_mode=S_IFREG|0644, st_size=243756, ...}) = 0
3691 mmap(NULL, 243756, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff0696c2000
3691 close(3) = 0
3691 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libcrypto.so.1.1", O_RDONLY|O_CLOEXEC) = 3
3691 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\t\0\0\0\0\0"..., 832) = 832
3691 fstat(3, {st_mode=S_IFREG|0644, st_size=3076960, ...}) = 0
...
有没有一种简单的方法可以只打印出路径,在这种情况下,使用 awk 似乎不容易解析路径?
答案1
我建议结合使用 grep 和 sed:
... | grep '"/' | sed 's/^.*"\(/[^"]*\)".*$/\1/'
这可能会从恰好以斜杠开头的数据字符串中产生一些误报,并且对于包含文字双引号的路径名也可能会失败,并且它不会在一行中找到第二条路径,但这是一个开始......
您还可以 grep 查找“openat”和其他带有路径参数的系统调用:
... | grep -e openat -e access | sed ...
以进一步减少误报。
答案2
使用 GNU awk 作为第三个参数match()
:
$ awk 'match($0,/"(\/[^"]+)/,a){print a[1]}' file
/etc/suid-debug
/etc/ld.so.preload
/etc/ld.so.cache
/lib/x86_64-linux-gnu/libcrypto.so.1.1
否则,在每个 Unix 机器上的任何 shell 中使用任何 awk:
$ awk 'match($0,/"\/[^"]+/){print substr($0,RSTART+1,RLENGTH-1)}' file
/etc/suid-debug
/etc/ld.so.preload
/etc/ld.so.cache
/lib/x86_64-linux-gnu/libcrypto.so.1.1
答案3
你可以这样做:
grep -Po '(\(|, )"\K/[^"]*'
"
查找以 or 开头的/
非("
字符序列, "
。
这甚至可能就足够了:
grep -Po '"\K/[^"]*'
"
对于以 开头的非字符序列,/
后面跟随"
.
他们只会报告绝对路径(以 开头的路径/
)。他们可能会报告一些不属于路径的事情,例如 in ,write("// some C++ comment", ...)
而后者可能会被诸如 之类的事情愚弄write("foo \"/bar\" baz"...)
。
对于允许相对路径的更严格匹配,您需要覆盖正则表达式中采用路径参数的所有系统调用。从你的样本来看:
grep -Po '^\d+\s+((open|access)\(|openat\(\S+, )"\K(\\.|[^"])*'
要从失败的系统调用中排除路径,您可以将(?!.*\) = -1)
(否定的前瞻断言)附加到您的正则表达式中。另请参见-z
//选项,以及仅跟踪与文件相关的系统调用--successful-only
。-e status=successful
strace
-e trace=%file