私はstdoutとstderrがインターリーブされずに簡単に識別できるように視覚的に分離する方法を探しています。理想的には、stdoutとstderrには、画面上のさまざまな列など、別々の表示領域があります。たとえば、出力は次のようになります。
~$ some command
some useful output info
ERROR: an error
more output
ERROR: has occurred
another message
~$
代わりに次のようになります。
~$ some command |
some useful output info |
more output | ERROR: an error
another message | ERROR: has occurred
~$ |
ベストアンサー1
screen
GNUの垂直分割機能を使用できます。
#! /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"
たとえば、次のように使用されます。
that-script 'ls / /not-here'
アイデアは、垂直に分割されたレイアウトで2つの画面ウィンドウを起動する一時的なconfファイルで画面を実行することです。最初のコマンドでは、コマンドを実行し、stderrを2番目のコマンドに接続します。
2番目のウィンドウの名前付きパイプを使用して最初のウィンドウとttyデバイスを通信し、最初のウィンドウはコマンドが完了すると2番目のウィンドウに通知します。
パイプベースのアプローチに比べてもう1つの利点は、コマンドのstdoutとstderrがまだttyデバイスに接続されているため、バッファリングに影響を与えないことです。どちらのウィンドウも独立して上下にスクロールできます(コピーscreen
モードを使用)。
このスクリプトを使用してシェルを対話的に実行すると、プロンプトがbash
2番目のウィンドウに表示され、最初のウィンドウに入力した内容がシェルによって読み取られます。なぜなら、このシェルはstderrにプロンプトを出力するからです。
の場合bash
、エコ入力した内容が2番目のウィンドウにも表示されます。エコbash
また、シェルによってstderrに出力されます(この場合はreadline)。たとえば、他のシェルの場合は、最初のウィンドウksh93
に表示されます(エコemacs
シェルを使用したり、シェルをvi
モードに設定したりしない限り、シェルではなくターミナルデバイスドライバによって出力されます。set -o emacs
set -o vi