コマンドの出力を変数に保存し、teeを使用せずに印刷しますか?

コマンドの出力を変数に保存し、teeを使用せずに印刷しますか?

コマンド出力を変数に保存し、リアルタイムで印刷する方法を見つけようとしています。最初はteeうまくいくような例を見つけました。

VARIABLE=$(./build.sh | tee /dev/tty)

ただし、問題は、仮想コンソール(git ハブアクションなど)があるシステムで実行するとエラーが発生することですtee: /dev/tty: No such device or address。出力を変数に保存し、リアルタイムで正常に印刷する方法を探したいです(例:echo、printfなど)。

答え1

これを使用するときの問題は、/dev/ttystdoutが元のttyに添付されていると仮定することです。これは必ずしもGitHub Actionsが示すわけではありません。これは、スクリプトの標準出力を別の場所(ログファイルなど)にリダイレクトする場合にも問題になる可能性があります。

teeに渡すことは、$(...)プロセス交換前のstdout(bits)です。プロセス置換は出力をキャプチャするために stdout を使用します。 Bashや他のシェルは、ユースケースに応じてファイル記述子を操作できます。

exec 3>&1  # Open FD 3 as a duplicate of stdout (fd 1)
# Run ./build.sh but make sure it does not have FD 3 open and tee to FD 3
VARIABLE=$(./build.sh 3>&- | tee /dev/fd/3)
exec 3>&-  # Close FD 3

これにより、スクリプトの標準出力をスクリプト外で操作(ロガーや/dev/nullなどにリダイレクト)できるため、WRT標準出力の正しい動作が維持されます。

@SOUserがコメントで指摘したように、スクリプト出力をファイルに書き込むのに問題があります。問題は、tee /dev/fd/3ファイルを開くとファイルが切り捨てられ、ファイルに書き込まれたすべての内容が削除されることです。この問題を解決しようとすると、さらにtee -a /dev/fd/3奇妙な動作が発生します。何らかの理由でキャプチャする行が完全に欠落しています。

解決策はファイルの代わりにパイプに書き込むことですので、./script > test.log使用しないでください./script | cat > test.log。この方法では、teeファイルがファイルに添付されず、切り捨てられないパイプに添付されるため、ファイルを切り捨てることはできませんcat

答え2

stderrに提供することができます。

VARIABLE=$(./build.sh | tee /dev/stderr)

関連情報