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

我有一些脚本应该停止运行,但永远不会停下来。

有什么方法可以找出他们正在写入标准输出和标准错误以可读的方式吗?

例如,我试图做

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

但那不是真的有用。 无论如何,这是一个长镜头。

任何其他的想法? 因为看到这一点,它本身是非常冗长和不可读的。

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

我不确定它是否能为你工作,但是我读了一个页面,然后描述了一个使用gdb的方法

由于我不允许编辑Jauco的答案,因此我会给出完整的答案(罗素的页面依赖于无担保的行为,如果closures标准输出1,标准输出将打开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 

现在你可以尾巴/ tmp /标准输出,并看到用于输出标准输出。

有几个新的实用程序,包装“gdb方法”,并添加一些额外的触摸。 我现在使用的是“reptyr”(“Re-PTY-er”)。 除了抓取STDERR / STDOUT之外,它实际上会改变一个进程的控制terminal(即使它以前没有连接到terminal)。

最好的方法是启动一个屏幕会话,并使用它将正在运行的进程重新附加到屏幕内的terminal上,以便您可以安全地从其中卸载并稍后再回来。

它包装在stream行的发行版(例如:“apt-get install reptyr”)。

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

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

strace -p -e write = 1 -s 1024 -o文件

  -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. 

这打印出来比你需要的更多(hex部分),但是你可以很容易地把它打印出来。

我用strace和解码hex输出清除文本:

 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" 

我结合了这个命令从其他答案。

strace输出很less,只是-ewrite(而不是= 1后缀)。 这比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 

你可以使用reredirect( https://github.com/jerome-pouiller/reredirect/ )。

types

 reredirect -m FILE PID 

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

reredirect README还解释了如何恢复进程的原始状态,如何redirect到另一个命令或只redirectstdout或stderr。

你没有说明你的操作系统,但是我会采取一个刺的方式来说“Linux”。

看到什么是写入stderr和stdout可能不会帮助。 如果它有用,可以在开始脚本之前使用tee(1)来获取stderr和stdout的副本。

你可以使用ps(1)来寻找wchan。 这告诉你该进程正在等待什么。 如果您查看strace输出,则可以忽略大部分输出,并确定最后(阻止)的系统调用。 如果是对文件句柄的操作,则可以在输出中向后走,并确定底层对象(文件,套接字,pipe道等)。从那里,答案可能会很清楚。

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