2009-08-01 6 views

答えて

31

技術的に言えば、stderrをstdoutに複製またはコピーします。

通常、これを実行するためにexecは必要ありません。ファイルディスクリプタでのexecのより一般的な使い方は、ファイルを未使用のファイルディスクリプタに割り当てることを指定することです。ところで

exec 35< my_input

は、それがファイルmydirlistの両方stdoutとstderrを指示するのでそう

ls > mydirlist 2>&1 

は一方で、動作しますが、ファイルへの配管宣言の順序が重要であることを忘れてはいけません標準エラー出力がstdou前に標準出力のコピーを作ったため、コマンド

ls 2>&1 > mydirlist 

は、mydirlistを提出し、唯一のstdout、およびstderrのではないに指示しますtはmydirlistにリダイレクトされました。

編集:これは、シェルが左から右にスキャンする方法です。 "stdoutをstdoutにコピーする"と言う前に、 "stdoutをmydirlistに送る"と言う前に、2番目のものを読んでください。それから私が設定したstdoutにstderrを複製する前に "stdoutをファイルmydirlistに送る"と言って最初のものを読んでください。知っている。それはまったく直感的ではありません!

+0

申し訳ありませんが、私はこれを理解していません。 stderrをstdoutに指定してからstdoutをファイルに出力することはできませんが、stdoutをファイルに出力し、stderrをstdoutに渡します。それは正反対でなければならないようです。 –

+1

@bjarkef、上記の編集をご覧ください。 –

+0

確かに非常に直観的なカウンターカウンター。私は何度も何も知らず、なぜそれがうまくいかないのか疑問に思っていたので、それを正確にやろうとしてきました。本当にありがとう。 –

10

それは標準外

2に標準誤差を結びつけることは標準エラー出力で、1はstdoutです。プログラムを実行すると、標準出力がstdoutに出力されますが、エラーや警告は通常stderrに送られます。たとえば、すべての出力をファイルにパイプしたい場合は、最初にstderrをstdoutと組み合わせて2>&1にすると便利です。

+1

呼び出し幹部は必ずしも私がnontheless隠し機能(その浅ドキュメント内)が、新しいことではありません。面白いこと.. –

+0

stderrをstdoutにパイプしません。あなたはstderrをstdoutと結びつけるか、stderrとstdoutを関連付けると言うことができます。データはパイプ処理され、ファイル記述子はパイプ処理されません。 –

+0

ありがとう、ウィリアム、私はそれを 'ネクタイ'に変更しました –

2

@cmaと同様、stderrを標準出力に置きます。この動作が必要な理由は、grepやその他のユーティリティを使用してstderrにのみ表示される出力をキャプチャすることです。あるいは、後で処理するために、stderrを含むすべての出力をファイルに保存したいだけかもしれません。

22

「2> & 1」のような優れた記事は、Bash One-Liners Explained, Part III: All about redirectionsです。

しかし、この質問の現在の回答が提供していないのは、単純な「exec」の後にこれを行う理由です。 execコマンドのbash manページには、「コマンドが指定されていない場合、現在のシェルでリダイレクションが有効になります」と説明されています。

私はstdoutに出力の行を書き込み、別の行はstderrにout-and-err.pyと呼ばれる簡単なスクリプトを書きました:

#!/usr/bin/python 
import sys 
sys.stdout.write('this is stdout.\n') 
sys.stderr.write('this is stderr.\n') 

をそして私は、シェルスクリプト内で呼び出されることに包まれました - と - エラー。"2> & 1のexec" とSH:

#!/bin/bash 
exec 2>&1 
./out-and-err 

私はPythonスクリプトを実行する場合は、stdoutとstderrが別々である:

$ ./out-and-err.pl 1> out 2> err 
$ cat out 
this is stdout. 
$ cat err 
the is stderr. 

しかし、私はシェルスクリプトを実行した場合、あなたが見ることができます幹部は、後にすべてのために標準エラー出力の世話をすること:あなたのラッピングシェルスクリプトが一つだけのpythonコマンドよりも多くない、とあなたが標準出力に結合されたすべての出力を必要とする

$ ./out-and-err.sh 1> out 2> err 
$ cat out 
this is stdout. 
this is stderr. 
$ cat err 
$ 

場合は、 「exec 2> & 1」を実行すると、それが簡単になります。あなたはセミコロンで区切って複数のコマンドのためにstderrstdoutをマージするときに私が遭遇したexec 2>&1

+1

すごい答えですが、他の人はリダイレクトがシェル(またはスクリプト)全体で有効であると説明するのに失敗しました!この例では明確になっています。 – caesarsol

0

一つの非常に便利なアプリケーションです。私の特定の例は、私はPHPでpopenに複数のコマンドを送信した際に起こったと私はエラーがシェルプロンプトでコマンドを入力した場合、あなたが見ることのようにインターリーブ見たかった:

$ echo hi ; yikes ; echo there 
hi 
-bash: yikes: command not found 
there 
$ 

がマージされません、次の最後echoを除くstderrstdoutyikesがエラーを引き起こすので無意味である):

echo hi ; yikes ; echo there 2>&1 

次のように私は、マージされた出力に「苦労」を得ることができます。

echo hi 2>&1; yikes 2>&1; echo there 2>&1 

あなたがexecを使用する場合、それは多くのクリーナーとよりエラーが発生しやすい見える:

exec 2>&1 ; echo hi; echo yikes; echo there 

あなたが区切られた3つのコマンドを実行した場合は、端末上で見ることとしてstdoutstderr出力がきれいに正確にインターリーブ取得セミコロンで。

関連する問題