在两个单独的流中显示 stdout 和 stderr

Zoe*_*wll 18 command-line terminal

我正在寻找一种在视觉上分离 stdout 和 stderr 的方法,这样它们就不会交错,从而可以轻松识别它们。理想情况下,stdout 和stderr 在显示它们的屏幕上会有不同的区域,例如在不同的列中。例如,输出看起来像这样:

~$ some command
some useful output info
ERROR: an error
more output
ERROR: has occurred
another message
~$ 
Run Code Online (Sandbox Code Playgroud)

而是看起来像这样:

~$ some command          |
some useful output info  |
more output              |  ERROR: an error
another message          |  ERROR: has occurred
~$                       |
Run Code Online (Sandbox Code Playgroud)

Sté*_*las 9

您可以使用 GNUscreen的垂直拆分功能:

#! /bin/bash -
tmpdir=$(mktemp -d) || exit
trap 'rm -rf "$tmpdir"' EXIT INT TERM HUP

FIFO=$tmpdir/FIFO
mkfifo "$FIFO" || exit

conf=$tmpdir/conf

cat > "$conf" << 'EOF' || exit
split -v
focus
screen -t stderr sh -c 'tty > "$FIFO"; read done < "$FIFO"'
focus
screen -t stdout sh -c 'read tty < "$FIFO"; eval "$CMD" 2> "$tty"; echo "[Command exited with status $?, press enter to exit]"; read prompt; echo done > "$FIFO"'
EOF

CMD="$*"
export FIFO CMD

screen -mc "$conf"
Run Code Online (Sandbox Code Playgroud)

例如用作:

that-script 'ls / /not-here'
Run Code Online (Sandbox Code Playgroud)

这个想法是它使用临时 conf 文件运行 screen ,该文件以垂直拆分布局启动两个屏幕窗口。在第一个中,我们使用连接到第二个的 stderr 运行您的命令。

我们为第二个窗口使用命名管道将其 tty 设备与第一个窗口通信,并在命令完成后第一个窗口通知第二个窗口。

与基于管道的方法相比,另一个优点是命令的 stdout 和 stderr 仍然连接到 tty 设备,因此它不会影响缓冲。两个窗格也可以独立上下滚动(使用screen的复制模式)。

如果您bash使用该脚本以交互方式运行 shell ,您会注意到提示将显示在第二个窗口中,而 shell 将读取您在第一个窗口中键入的内容,因为这些 shell 在 stderr 上输出它们的提示。

在 的情况下bash,您键入的内容的回声也将出现在第二个窗口中,因为该回声也是由 shell(在 的情况下为 readline bash)在 stderr 上输出的。对于其他一些 shell,如ksh93,它将显示在第一个窗口上(终端设备驱动程序的回显输出,而不是 shell),除非您将 shell 置于emacsorvi模式下set -o emacsset -o vi