一个进程如何拦截Linux上另一个进程的stdout和stderr?

时间:2008-10-30 09:55:51

标签: linux stdout

我有一些脚本应该已经停止运行但是永远都会流连忘返。

有什么方法可以用可读的方式弄清楚他们写给stdout和stderr的内容了吗?

我试过,例如,

tail -f /proc/(pid)/fd/1

但这确实不起作用。无论如何,这是一个很长的镜头。

还有其他想法吗?因为看到这一点,它本身就非常冗长和难以理解。

注意:我对其输出感兴趣,而不是其他任何东西。我有能力自己搞清楚其他事情;这个问题只关注在启动之后访问正在运行的进程的stdout和stderr。

8 个答案:

答案 0 :(得分:41)

由于我不允许编辑Jauco的答案,我会给出适合我的完整答案(Russell的页面依赖于无保障的行为,如果你关闭stdout的fd 1,下一个creat会打开fd 1

所以,运行这样一个简单的无尽脚本:

import time

while True:
    print 'test'
    time.sleep(1)

将其保存到test.py,使用

运行
python test.py

获取pid:

ps auxw | grep test.py

现在,附上gdb:

gdb -p (pid)

并做fd魔术:

(gdb) call creat("/tmp/stdout", 0600)
$1 = 3
(gdb) call dup2(3, 1)
$2 = 1

现在你可以tail / tmp / stdout并查看以前用于stdout的输出。

答案 1 :(得分:9)

有几个新的实用程序包含了“gdb方法”并添加了一些额外的功能。我现在使用的那个叫做“reptyr”(“Re-PTY-er”)。除了抓住STDERR / STDOUT之外,它实际上会改变一个进程的控制终端(即使之前没有连接到终端)。

最好的用途是启动一个屏幕会话,并使用它将一个正在运行的进程重新连接到屏幕上的终端,这样你就可以安全地从它上面分离并稍后再回来。

它包装在流行的发行版上(例如:'apt-get install reptyr')。

http://onethingwell.org/post/2924103615/reptyr

答案 2 :(得分:8)

Gdb方法似乎更好,但你也可以用strace做到这一点:

strace -p -e write = 1 -s 1024 -o file

   -e write=set
               Perform a full hexadecimal and ASCII dump of all the
               data written to file descriptors listed in the spec-
               ified  set.  For example, to see all output activity
               on file descriptors 3 and 5 use -e write=3,5.   Note
               that  this is independent from the normal tracing of
               the write(2) system call which is controlled by  the
               option -e trace=write.

这打印出的比你需要的更多(十六进制部分),但你可以很容易地把它打开。

答案 3 :(得分:7)

我不确定它是否适合您,但我在前一段时间阅读了一页,描述了method that uses gdb

答案 4 :(得分:4)

我使用了strace并对十六进制输出进行了解码以清除文本:

PID=some_process_id
sudo strace -f -e trace=write -e verbose=none -e write=1,2 -q -p $PID -o "| grep '^ |' | cut -c11-60 | sed -e 's/ //g' | xxd -r -p"

我将此命令与其他答案结合起来。

答案 5 :(得分:2)

仅使用-ewrite(而不是= 1后缀)

strace输出少得多。它比gdb方法简单,imo。

我用它来查看现有MythTV编码作业的进度(sudo因为我没有编码过程):

$ ps -aef | grep -i handbrake
mythtv   25089 25085 99 16:01 ?        00:53:43 /usr/bin/HandBrakeCLI -i /var/lib/mythtv/recordings/1061_20111230122900.mpg -o /var/lib/mythtv/recordings/1061_20111230122900.mp4 -e x264 -b 1500 -E faac -B 256 -R 48 -w 720
jward    25293 20229  0 16:30 pts/1    00:00:00 grep --color=auto -i handbr

$ sudo strace -ewrite -p 25089
Process 25089 attached - interrupt to quit
write(1, "\rEncoding: task 1 of 1, 70.75 % "..., 73) = 73
write(1, "\rEncoding: task 1 of 1, 70.76 % "..., 73) = 73
write(1, "\rEncoding: task 1 of 1, 70.77 % "..., 73) = 73
write(1, "\rEncoding: task 1 of 1, 70.78 % "..., 73) = 73^C

答案 6 :(得分:2)

您可以使用重新定向(https://github.com/jerome-pouiller/reredirect/)。

类型

reredirect -m FILE PID

和输出(标准和错误)将写入文件。

reredirect README还解释了如何恢复原始进程状态,如何重定向到另一个命令或仅重定向stdout或stderr。

答案 7 :(得分:1)

你没有陈述你的操作系统,但我会采取刺戳并说“Linux”。

看到写入stderr和stdout的内容可能无济于事。如果它很有用,你可以在开始脚本之前使用tee(1)来获取stderr和stdout的副本。

您可以使用ps(1)查找wchan。这告诉您进程正在等待什么。如果查看strace输出,可以忽略大量输出并识别最后一个(阻塞的)系统调用。如果它是对文件句柄的操作,你可以在输出中向后移动并识别底层对象(文件,套接字,管道等)。从那里答案可能很清楚。

您还可以向进程发送一个信号,使其转储核心,然后使用调试器和核心文件来获取堆栈跟踪。