如何从日志文件中提取路径名?

如何从日志文件中提取路径名?

这类似于例如,但不完全是;我将 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

相关内容