'>'がgccからエラーメッセージをリダイレクトしないのはなぜですか?


9

次のプログラムをnew.cに保存しました

int main() 
{ 
    a;
    return 0; 
}

エラーメッセージを返します。このメッセージをファイルに送信したい。だから私は次のコマンドを使用しました

gcc new.c > temp.txt

しかし、それでも私はターミナルで出力を得ていました。私はUbuntu 13.04を使用しています。どうすれば機能させることができますか?


回答:


16

を使用してプログラムをコンパイルするとgcc、出力の種類が異なります:to stdoutstderr。通常、>指示するstdout(例えば、結果をファイルにストリームprintf("hello world\n");に送られますstdout)。ただし、stderr「通知が必要な例外的なもの」であると想定されるため、画面には引き続きが送信されます。

stderrをファイルにリダイレクトする方法があります。これを行うには、次の(あまり直感的ではない)コマンドを使用します。

gcc new.c &> myFile

ここで&>、「すべてリダイレクト」の「bash省略形」です。@CharlesDuffyによって指摘されたように、POSIX準拠のフォームは

gcc new.c > myFile 2>&1

これは、「new.cをコンパイルしてに送信stdoutmyFileます。stderr(2)をstdout&1=「stdoutと同じ場所」)と同じ場所に送信します。

さまざまなリダイレクトの詳細については、http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-3.htmlおよびhttp://mywiki.wooledge.org/BashFAQ/055を参照してください。

ちなみに、プログラム内からに何かを送信したい場合は、次のようにして送信stderrできます。

fprintf(stderr, "hello world - this is urgent.\n");

それをプログラムに含め、プログラムを実行し、「通常の」出力をファイルに送信すると、これは引き続きコンソールに表示されます。したがって、上記を実行可能ファイルにコンパイルする場合は、次のように入力しますurgent

./urgent > /dev/null

コンソールで、出力が画面に表示されます。


2
mywiki.wooledge.org/BashFAQ/055は、おそらくリダイレ​​クトのより良い紹介です。また、POSIX準拠のフォーム(>myFile 2>&1)とbash拡張(&>)を実際に導入する必要があります。
Charles Duffy

@CharlesDuffy-両方の非常に良い点。完全を期すために、回答に含めます。
フローリス2013年

11

ので>リダイレクトのみstdout、およびエラーが書き込まれstderr、あなたの代わりに、次のいずれかを使用する必要があります。

gcc new.c &> temp.txt ## redirect both stdout and stderr using bash or zsh only

...または...

gcc new.c >temp.txt 2>&1 ## redirect both stdout and stderr in any POSIX shell

&>両方stdoutstderrファイルにリダイレクトするBASH拡張機能です。それ以外の場合、最も簡単な方法は、最初にstdout(>temp.txt)をリダイレクトし、次にstderr(FD 2)をstdout(FD 1)の既にリダイレクトされたファイルハンドルのコピーにすることです2>&1


4

他の人が言ったように、linuxは2つの異なる出力ストリームを提供します:

stdoutまたは「標準出力」は、すべての通常の出力が行われる場所です。
              ファイル記述子を使用して参照できます1

stderrまたは「標準エラー」は、帯域外情報の個別のストリームです。
              ファイル記述子を使用して参照できます2

なぜ2つの異なる出力ストリームがあるのですか?架空のコマンドのパイプラインを考えます。

 decrypt $MY_FILE | grep "secret" | sort > secrets.txt

decryptコマンドが失敗し、エラーメッセージが生成されることを想像してください。そのメッセージをstdoutに送信した場合、パイプに送信されます。「秘密」という単語がなければ、メッセージは表示されません。したがって、何が問題だったかわからないまま、空の出力ファイルが作成されます。

ただし、パイプはをキャプチャするだけなstdoutので、decryptコマンドはエラーをstderrに送信し、コンソールに表示されます。

stdoutおよびstderrは、一緒にまたは個別にリダイレクトできます。

# Send errors to "errors.txt" and output to "secrets.txt"
# The following two lines are equivalent, as ">" means "1>"
decrypt $MY_FILE 2> errors.txt > secrets.txt
decrypt $MY_FILE 2> errors.txt 1> secrets.txt

エラーをリダイレクトして、stdout通常の出力であるかのように処理できます。

# The operation "2>&1" means "redirect file descriptor 2 to file
# descriptor 1. So this sends all output from stderr to stdout.
# Note that the order of redirection is important.
decrypt $MY_FILE > errors.txt 2>&1 

# This may be confusing.  It will store the normal output in a file
# and send error messages to stdout, where they'll be captured by 
# the pipe and then sorted.
decrypt $MY_FILE 2>&1 > output.txt | sort

「省略形」表記を使用して、stdoutとstderrの両方を同じファイルにリダイレクトすることもできます。

decrypt $MY_FILE &> output.txt

そして最後に、>オペレーターは、出力ファイルに書き込む前に、まずその出力ファイルを切り捨てます。代わりに、既存のファイルにデータを追加する場合は、>>演算子を使用します。

decrypt $MY_FILE 2>> more_errors.txt >> more_secrets.txt
decrypt $MY_FILE >> more_output.txt 2>&1

1
2つの難点:(1)引用符で囲まれていないパラメーター展開($FOO)の使用は、バグの一般的な原因であり、例でそれを示すことはそれほど大きくありません。(2)すべて大文字の変数名を使用することが、環境変数と組み込み変数(慣習では大文字)とローカル変数(慣習では小文字)の間で名前空間が競合する主な理由です。(3)>>ファイルを一度開いて複数のコマンドで使用するためにファイル記述子を開いたままにするのではなく、繰り返し使用する(コマンドで使用されるたびにファイルを開く)ように人々に勧めると、コードの効率が悪くなります。
Charles Duffy

...と比較する最後のポイント、上: exec 4>secrets; echo "this is a secret" >&4; echo "this is another secret" >&4
チャールズ・ダフィー

+1 @CharlesDuffy、正直に教えてくれてありがとう。すべての良い点。exec単純化のために意図的に省略しましたが、実際には一般的にはより良い戦略です。

また、またはに折りたたむこともできます(の前後にスペースがあり、の前にa がある必要があります)。command₁ > output_file ; command₂ >> the_same_output_file( command₁ ; command₂ )  > output_file{ command₁ ; command₂ ;  }  > output_file{;}
G-Manは 'Reinstate Monica'を
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.