我编写了以下代码来确定程序写入哪些文件。我当然想捕获文件名。
strace -f -t -e trace=file -p 8804 2>&1 | grep -oP "\"(.*)\".*O_WRONLY"
这输出类似
/tmp/11111111.txt", O_WRONLY
问题是我无法将所有这些输出传输到任何命令
strace -f -t -e trace=file -p 8804 2>&1 | grep -oP "\"(.*)\".*O_WRONLY" | echo
# does not show anything
而且我也无法保存所有这些的输出以供以后使用:
strace -f -t -e trace=file -p 8804 2>&1 | grep -oP "\"(.*)\".*O_WRONLY" > asd.out
# file is empty
感谢您的帮助。 :)
答案1
您可以将输出写入文件(使用strace -o asd.out
),然后 grep 它:
来自 strace 手册:
-o filename Write the trace output to the file filename rather than
to stderr. Use filename.pid if -ff is used. If the argument begins with
`|' or with `!' then the rest of the argument is treated as a command
and all output is piped to it. This is convenient for piping the
debugging output to a program without affecting the redirections of
executed programs.
答案2
今天遇到了同样的问题。
FWIW 您可以在示例中使用| cat
而不是,显然默认情况下不带任何参数不执行任何操作。| echo
echo
在我的盒子上strace ls 2>&1 | grep "execve" > asd.out
实际上工作正常......所以你做得对。
我的预感是问题出在“附加”中,strace -p xxx
因为通常您必须点击ctrl+c
才能退出它,并且命令链中的中间缓冲区是没有冲水。
所以这对我有用(我认为它刷新在一个新行上,因为它检测到它输出到“屏幕”/终端/tty):
strace ruby -e "sleep" 2>&1 | grep execve
但这并不
strace ruby -e "sleep" 2>&1 | grep execve > my_output_file
(我认为因为最终的重定向是“不是到 tty”,所以它使用更大的 4k 内部缓冲区或其他东西,或者使用内部缓冲区而不是“按行”缓冲)。
但是使用来自的提示这里,这有效:
strace ruby -e "sleep" 2>&1 | stdbuf -oL grep execve > me
很奇怪的东西。以一种令人不安的方式。我的理论是,对于更长的链(例如:grep | grep | grep
缓冲区的大小线性增长...每次 4k...包括最终将其写入磁盘的那一个...)
另一件可以帮助的事情是在你的链中插入一个“输出到屏幕”窥视器,这显然是tee /dev/tty
:
strace ruby -e "sleep" 2>&1 | tee /dev/tty | grep execve > my_output_file
那么至少你会在屏幕上看到它,即使它从未进入输出文件。
所以无论如何,strace 会记录为“正常” stderr
(因此,如果它是“运行一个进程”,例如,strace ls
那么进程和 strace 的输出将是混合的)。您可以通过使用该参数来避免混合-o output_file
。
另请注意,必须先重定向 stdout,然后重定向 stderr,例如:
progname >out.txt 2>&1
顺序很重要,不能反过来。