私の目標は、コマンドを呼び出し、変数にstderrを取得することですが、stdout(およびstdoutのみ)を画面に表示したままにします。うん、それはほとんどの人がすることの反対です:)
今のところ、私が持っている最高のものは:
#!/bin/bash
pull=$(Sudo ./pull "${TAG}" 2>&1)
pull_code=$?
if [[ ! "${pull_code}" -eq 0 ]]; then
error "[${pull_code}] ${pull}"
exit "${E_PULL_FAILED}"
fi
echo "${pull}"
ただし、これは、成功した場合、およびコマンドの終了後にのみ標準出力を表示できます。 stdoutをライブで使用したいのですが、これは可能ですか?
[〜#〜]編集[〜#〜]
@sebasthのおかげで、そして STDERRとSTDOUTを一時ファイルなしで別の変数にリダイレクトする の助けを借りて、私はこれを書きます:
#!/bin/bash
{
Sudo ./pull "${TAG}" 2> /dev/fd/3
pull_code=$?
if [[ ! "${pull_code}" -eq 0 ]]; then
echo "[${pull_code}] $(cat<&3)"
exit "${E_PULL_FAILED}"
fi
} 3<<EOF
EOF
私はこれが本当に「きれい」ではないことを認め、トリッキーに見えますが、なぜヘレドックが必要なのか本当にわかりません...
これはそれを達成するためのより良い方法ですか?
ただ使う:
{ err=$(cmd 2>&1 >&3 3>&-); } 3>&1
Stdoutを変更せずにcmd
のstderrを取得するには(ここではfd 3を使用してbringコマンド置換内の元のstdout(3>&1
でコピー))( >&3
は、2>&1
)を使用したコマンド置換によって作成されたパイプにfd 2をリダイレクトした後です。
StéphaneChazelas が提供する回答を少し変更して使用できます。stderrのみをリダイレクトし、コマンド置換を使用してコマンドを実行しないでください。
{
command 2> /dev/fd/3
res=$?
err=$(cat<&3)
} 3<<EOF
EOF
printf 'stderr: %s\n' "$err"
command
の出力は通常stdoutにあり、stderrはerr
変数にあります。
Stdrをキャプチャするコマンドのstdoutとstderrを交換するだけです。
pull=$(Sudo ./pull "${TAG}" 3>&2 2>&1 1>&3)
そして、stderrをstdoutにリダイレクトします。
{ pull=$(Sudo ./pull "${TAG}" 3>&2 2>&1 1>&3; } 2>&1
説明:
コマンドのstdoutのみをキャプチャする場合と同じ方法で:
var=$(cmd)
stderrの出力は引き続きコマンドラインに送られます。両方のチャネルを交換して、stderrのみをキャプチャできます。
var=$(cmd 3>&2 2>&1 1>&3)
次に、stderrをstdoutにリダイレクトします(出力がある場合)。
{ var=$(f 3>&2 2>&1 1>&3); } 2>&1
両方からの回答を組み合わせる スクリーンオーバーライドリダイレクトに出力する方法 および bashキーワードのstderrをキャプチャする方法(時間など)? 、
var=$( (cmd >/dev/tty) 2>&1)
組み込みまたはキーワードを使用していない場合は、
var=$( cmd 2>&1 >/dev/tty )