如何将 stdout 和 stderr 保存到文件同时仍然可以看到输出?

如何将 stdout 和 stderr 保存到文件同时仍然可以看到输出?

我正在尝试调试一个生成大量数据的程序。但是我想要调试的事件在一段随机时间后发生(我无法强制执行)。因此,我需要在 shell 中查看 stdout 和 stderr,并将相同的输出保存到文件中以供进一步分析,并在 shell 输出中看到所需内容时立即中断。

我找到了script这个命令询问 Ubuntu 主题但我无法让它工作,脚本说:

$ script "./client -p 4242 -n test"
Script started, output file is ./client -p 4242 -n test

然后退出。该文件包含:

Script started on Thu Jun 26 13:51:12 2014

Script done on Thu Jun 26 13:51:12 2014

所以script不起作用。该./client文件是一个python脚本。我也尝试用启动它,$ python client -p 4242 -n test但它也不起作用。

我也在同一线程上看到一些带有tee管道的答案,但我无法将其输出到我的 shell 并查看发生了什么:

$ ./client -p 4242 -n test | tee output.log

给我一个等待的光标,但什么也没有发生。所以tee不起作用

还有其他解决方案吗?或者我注定要等待一段时间并中断程序并希望它经历我正在寻找的事件?

非常感谢您的帮助!

PS 我使用的是 zshell (带有 oh-my-zsh)、Mac OSX 10.9.3、Python 2.7.5

编辑:我可能不得不提一下,我正在使用该multiprocessing模块,并且该./client脚本启动了多个其他Processes。可能是因为这个原因吗?我仍然不明白为什么它无法捕获./client进程输出...

编辑2:我尝试了下面 Matteo 的答案(非常感谢您的帮助)但它变得越来越奇怪:

如果该过程失败(服务器关闭),我可以看到输出:

$ ./client -p 4242 -n test 2>&1 | tee output.log
Process Process-1:
Client # 1: Could not connect to server. Stopping.
Spawner: New client # 1 started...
Done.
$

但如果它看起来正在运行,我什么也看不到:

$ ./client -p 4242 -n test 2>&1 | tee output.log
^C [voluntary interrupt after a lot of waiting]
$ cat output.log
$ 

在上面的日志中(失败的地方),你可以看到新进程打印Spawner尽管主程序 ( ) 是在主程序之后启动的,但它仍然运行。因此,这看起来像是一些非常奇怪的输出魔法。

答案1

您可以将标准错误重定向到标准输出,然后使用tee复制标准输出并将其存储到文件中。

$ ./client -p 4242 -n test 2>&1  | tee output.log

编辑:你可以尝试使用以下命令

$ ( echo "stdout" ; echo "stderr" 1>&2 ) 2>&1  | tee output.log

这两个echos 会在 stdout 和 stderr 上产生输出。您应该会看到两者,并且output.log

编辑

除了修改程序(flush)之外,您还可以尝试script -q其他几个工具,如关闭管道缓冲

答案2

胜利!

正如问题中提到的,我使用 pythonmultiprocessing.Process从主客户端生成新进程。因此,输出被缓冲,并等待缓冲区已满后再刷新,但似乎命令从未发生过这种情况| tee。因此永远不会打印任何内容并无休止地等待。

因此,sys.stdout.flush()解决方案是在每个print语句后添加一个如上所述这里

print "Player # " + int(self.id) + " joined the map"
sys.stdout.flush() #<==== THIS MAKES IT ALL WORK !

此后,Matteo 的答案非常有效,并且可以同时在 shell 和文本文件中进行输出。

$ ./client -p 4242 -n test 2>&1  | tee output.log`
$ cat output.log
Player # 1 joined the map.
Player # 1 updated it's inventory.
[...]

相关内容