私の目標は、コマンドを呼び出して変数から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}"
ただし、これは成功時とコマンドが完了した後にのみ標準出力を表示します。標準出力をストリーミングしたいです。これは可能ですか?
編集する
@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
私はこれが実際に「美しくない」ことを認め、難しいように見え、heredocがなぜ必要なのか本当に理解していません...
これがこれを達成するより良い方法ですか?
答え1
ちょうど使用:
{ err=$(cmd 2>&1 >&3 3>&-); } 3>&1
cmd
stdoutを変更せずにstderrを取得するには(ここではfd 3を使用して)インポートする3>&1
コマンド置換の元のstdout(コピー)(>&3
fd 2をコマンド置換によって生成されたパイプにリダイレクトした後に復元されます2>&1
)。
答え2
下記の回答をご利用いただけますスティーブン・チャジェラス少し修正: stderr をリダイレクトし、コマンドを置き換えずにコマンドを実行します。
{
command 2> /dev/fd/3
res=$?
err=$(cat<&3)
} 3<<EOF
EOF
printf 'stderr: %s\n' "$err"
の出力はcommand
通常stdoutにあり、stderrはerr
変数にあります。
答え3
stderrをキャプチャするコマンドで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
説明する:
コマンドの標準出力のみをキャプチャするときと同じ方法で:
var=$(cmd)
stderrへの出力はまだコマンドラインに移動します。両方のチャンネルを交換してstderrのみをキャプチャできます。
var=$(cmd 3>&2 2>&1 1>&3)
次に、stderrを再度stdoutにリダイレクトします(出力がある場合は表示するため)。
{ var=$(f 3>&2 2>&1 1>&3); } 2>&1
答え4
両方の回答を組み合わせる出力を画面オーバーレイにリダイレクトする方法そしてbashキーワード(時間など)の標準エラーをキャプチャする方法は?、私は得る
var=$( (cmd >/dev/tty) 2>&1)
組み込み関数やキーワードを使用しない場合は、次のように単純化できます。
var=$( cmd 2>&1 >/dev/tty )