我有一些脚本应该已经停止运行但是永远都会流连忘返。
有什么方法可以用可读的方式弄清楚他们写给stdout和stderr的内容了吗?
我试过,例如,
tail -f /proc/(pid)/fd/1
但这确实不起作用。无论如何,这是一个很长的镜头。
还有其他想法吗?因为看到这一点,它本身就非常冗长和难以理解。
注意:我仅对其输出感兴趣,而不是其他任何东西。我有能力自己搞清楚其他事情;这个问题只关注在启动之后访问正在运行的进程的stdout和stderr。
答案 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')。
答案 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)
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输出,可以忽略大量输出并识别最后一个(阻塞的)系统调用。如果它是对文件句柄的操作,你可以在输出中向后移动并识别底层对象(文件,套接字,管道等)。从那里答案可能很清楚。
您还可以向进程发送一个信号,使其转储核心,然后使用调试器和核心文件来获取堆栈跟踪。