bashでは、標準エラーを別のプロセスにパイプする方法を教えてください。


137

プロセスの標準出力を別のプロセスの標準入力にパイプする方法はよく知られています。

proc1 | proc2

しかし、proc1の標準エラーをproc2に送信し、標準出力を現在の場所に残したい場合はどうなりますか?次のbashようなコマンドを実行すると思います。

proc1 2| proc2

しかし、悲しいかな、いいえ。これを行う方法はありますか?


このような単純なリダイレクトはrc、別のシェルであるで行うことができます。例:proc1 |[2] proc2。いいですね。しかし、bashそうではありません。
Rolf

回答:


168

プロセスの置換もあります。これにより、プロセスがファイルの代わりになります。次のようにファイルに
送信できますstderr

process1 2> file

ただし、次のようにファイルをプロセスに置き換えることができます。

process1 2> >(process2)

stderr画面に送信してログファイルに追加する具体的な例を以下に示します

sh myscript 2> >(tee -a errlog)

23
これは、述べられた質問に正しく答え、@ paxdiabloによって受け入れられた答えになるはずです
mmlb 14

私はこれを試しました。それは仕事(なかったweston --help 2> >(less))、そしてそれは私の殻を破った、私は終了し、再度ログインする必要がありました。
ロルフ

1
@Rolfの両方weston --helplessキーボードの操作が必要であるが、そのうちの1つだけがそれを受信する場合、問題が発生する可能性があります。grep代わりに次のようなものでテストしてみてください。さらに、マウスとキーボードの両方の入力が、ウェストンではなく2番目のコマンドに送られる場合があります。
BeowulfNode42 2018年

88

次のトリックを使用してとを入れ替える ことができます。次に、通常のパイプ機能を使用します。stdoutstderr

( proc1 3>&1 1>&2- 2>&3- ) | proc2

提供stdoutstderrの両方が開始時に同じ場所に指摘し、これはあなたが必要なものを提供します。

x>yビットがないと、変更ファイルハンドルにあるx、それは今どこファイルハンドルにその情報を送信しますのでy、現在のポイント。私たちの特定のケースについて:

  • 3>&1現在のハンドル(元の標準出力)に出力する新しいハンドル3を作成し、以下の最後の箇条書きのためにどこかに保存します。1
  • 1>&2ハンドル1(stdout)を変更して、現在のハンドル2(元のstderr)に出力します。
  • 2>&3-ハンドル2(stderr)を変更して現在のハンドル3(元のstdout )に出力し、ハンドルを閉じます3-末尾のを介して)。

これは、ソートアルゴリズムで実際に表示されるswapコマンドです。

temp   = value1;
value1 = value2;
value2 = temp;

3
1>&2-ここで使用するだけでなく、ここで使用することの価値は何1>&2ですか?fdを2ただちに再オープン/再割り当てするだけなのに、なぜfdをクローズしたいのか分かりません。
dubiousjim 2012年

1
@dubiousjim、その特定のケースでは何の利点もありません。一貫性を保つためだけに実行したのではないかと思います。ファイルハンドル3を閉じることは、解放するための良いアイデアです。
paxdiablo 2012年

良い点、@ ovgolovin、私が編集してから7か月で誰もそれを取り上げなかったなんて信じられません。あなたの提案に従って修正されました。
paxdiablo 2013年

gccのmake(私のシステムでは色分けされています)がこの((make 3>&1 1>&2- 2>&3-)| less -R "で動作するようにしようとしているのに対し、「(ls -al 3>&1 1>&2- 2>&3-)| less -R "は期待どおりに機能します。
同期されていない2015

あなたの説明は、2番目の2つのリダイレクトについて前から後ろに向かっているようです。1>&2-は、ファイルハンドル2(元のstderr)をハンドル1(元のstdout)に設定します2>&3-は、ファイルハンドル3(コピーされたstdout)をハンドル2(元のstderr)に設定します。私が間違っているなら私を訂正してください。ところで、2のダッシュは、stdoutからのデータが入力されている間に、新しいstderrデータがこのバッファーに送信されないようにするためのものだと思います。
aghsmith '12

70

Bash 4には次の機能があります。

`|& 'を使用すると、command1の標準エラーはパイプを介してcommand2の標準入力に接続されます。2>&1 |の省略形です。この標準エラーの暗黙的なリダイレクトは、コマンドで指定されたリダイレクトの後に実行されます。

zshにもこの機能があります。

-

他の/古いシェルでは、次のように明示的に入力するだけです

FirstCommand 2>&1 | その他のコマンド


14
ドキュメントを読むと、stderrだけでなく、標準エラー出力の両方が実行されますが知っておくと便利です。bash 4を検討するときがきたと思います。
paxdiablo 2009年

現在のbashマニュアルには、「|&が使用されている場合、標準出力に加えて、コマンドの標準エラーがcommand2の標準入力に接続されています」と書か れています。これは明らかにOPが望んでいることではありません。
ピーター-モニカの復活2017年

@ PeterA.Schneider:OPは「標準出力を現在の場所に残す」と言っていますが、これはあいまいかもしれません。
追って通知があるまで一時停止。

あいまいさは見られません。あなたの提案(1)は、2つのストリームを統合します。(2)結合されたデータをどこかに、おそらく別の場所にOtherCommand書き込みます。そのため、同じデータではなく、別の場所に移動する可能性があります。それはOPの望みとは正反対ですよね。
ピーター-モニカの復活

@ PeterA.Schneider:他に標準出力の現在の場所はどこですか?場合はproc1標準出力へとstderrに出力すると、あなたは、標準エラー出力はの標準入力に行きたいproc2(PROC1のstdoutが起こっているところである)、そして、私の答えは、それを達成します。私は彼がどのようなOP与え尋ねた彼はおそらくないもののために、意図をお願いします。そこには潜在的なあいまいさがあります。OPは、stdoutとstderrを交換する答えを受け入れましたが、これは彼が要求したものではありません
追って通知があるまで一時停止。

27

スワッピングは問題を解決するので素晴らしいです。元のstdoutも必要ない場合に備えて、次の方法で行うことができます。

proc1 2>&1 1>/dev/null | proc2

順序は重要です。あなたは望まないでしょう:

proc1 >/dev/null 2>&1 | proc1

これはすべてをにリダイレクトするので/dev/null


0

これらのどれも実際にはうまく機能しませんでした。私が見つけた最善の方法はあなたが望んだことをすることです:

(command < input > output) 2>&1 | less

これcommandは、キーボード入力を必要としない場合にのみ機能します。例えば:

(gzip -d < file.gz > file) 2>&1 | less

gzipエラーを少なくする

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.