コマンド出力を変数に保存し、リアルタイムで印刷する方法を見つけようとしています。最初はtee
うまくいくような例を見つけました。
VARIABLE=$(./build.sh | tee /dev/tty)
ただし、問題は、仮想コンソール(git ハブアクションなど)があるシステムで実行するとエラーが発生することですtee: /dev/tty: No such device or address
。出力を変数に保存し、リアルタイムで正常に印刷する方法を探したいです(例:echo、printfなど)。
答え1
これを使用するときの問題は、/dev/tty
stdoutが元の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)