无需重定向即可捕获输出并将其保留在终端上

Ole*_*kov 4 io-redirection

我需要捕获一个守护进程的输出,该守护进程还包括一个按需模式,并根据输出是否进入 tty 表现出不同的行为。只需将 stdout 重定向到任何地方,它就会进入日志模式,在这种模式下它以不方便的格式写入数据,而在 ATM 中,重新配置它会花费太多时间来执行其他操作/修复它/询问作者。

我可以以某种方式像往常一样运行它 - 即没有重定向 - 但仍然可以获得它在文件中写入屏幕的所有内容的副本吗?

Sté*_*las 5

您可以使用socat使mydaemon的标准输出成为伪终端设备,并将写入那里的所有数据发送到管道socat

这里使用ls -l /proc/self/fd代替mydaemon

$ socat  -u 'exec:"ls -l /proc/self/fd",pty,raw' - | tee file.out
total 0
lrwx------ 1 stephane stephane 64 Aug 20 13:32 0 -> /dev/pts/25
lrwx------ 1 stephane stephane 64 Aug 20 13:32 1 -> /dev/pts/26
lrwx------ 1 stephane stephane 64 Aug 20 13:32 2 -> /dev/pts/25
lr-x------ 1 stephane stephane 64 Aug 20 13:32 3 -> /proc/30930/fd
Run Code Online (Sandbox Code Playgroud)

看看lsstdout 是如何成为新的 pty 设备的 ( /dev/pts/26)

如果你没有socat,你也可以使用script

$ script -qc 'stty raw; ls -l /proc/self/fd' file.out < /dev/null
total 0
lrwx------ 1 stephane stephane 64 Aug 20 13:35 0 -> /dev/pts/26
lrwx------ 1 stephane stephane 64 Aug 20 13:35 1 -> /dev/pts/26
lrwx------ 1 stephane stephane 64 Aug 20 13:35 2 -> /dev/pts/26
lr-x------ 1 stephane stephane 64 Aug 20 13:35 3 -> /proc/31010/fd
Run Code Online (Sandbox Code Playgroud)

< /dev/null这样script不会将您的终端设置为raw模式)。

但是请注意,在这种情况下,所有 stdin、stdout 和 stderr 都被重定向到该 pty。要使 stdin 和 stderr 与socat方法一样保持不变,您可以执行以下操作:

$ script -qc 'stty raw; exec <&3 2>&4 3<&- 4>&-; ls -l /proc/self/fd' file.out 3<&0 4>&2 < /dev/null
total 0
lrwx------ 1 stephane stephane 64 Aug 20 13:37 0 -> /dev/pts/25
lrwx------ 1 stephane stephane 64 Aug 20 13:37 1 -> /dev/pts/26
lrwx------ 1 stephane stephane 64 Aug 20 13:37 2 -> /dev/pts/25
lr-x------ 1 stephane stephane 64 Aug 20 13:37 3 -> /proc/31065/fd
Run Code Online (Sandbox Code Playgroud)

并非所有script实现/版本都支持-cor-q选项。

请注意,某些系统带有unbuffer expect用于此的脚本,但要注意它有几个错误和限制。