2>&1> output.logと2>&1の違い| tee output.log


35

次の2つのコマンドの違いを知りたかった

2>&1 > output.log 

そして

2>&1 | tee output.log

同僚の1人が2番目のオプションを使用してリダイレクトするのを見ました。私は2>&1が何をするか知っています、私の唯一の質問は、単純なリダイレクト「>」演算子を使用できるteeを使用する目的は何ですか?

回答:


11

2つのコマンドを別々に見る:

utility 2>&1 >output.log 

ここで、リダイレクトは左から右の方法で処理されるため、標準エラーストリームは最初に標準出力ストリームの場所(場合によってはコンソール)にリダイレクトされ、次に標準出力ストリームがファイルにリダイレクトされます。標準エラーストリームはそのファイルにリダイレクトされません

これの目に見える効果は、画面上の標準エラーで生成されたものと、ファイルの標準出力で生成されたものを取得することです。

utility 2>&1 | tee output.log

ここでは、標準エラーを標準出力ストリームと同じ場所にリダイレクトします。これは、両方のストリームがtee単一の混在出力ストリームとしてユーティリティにパイプされ、この標準出力データがによって指定されたファイルに保存されることを意味しますtee。さらに、データはteeコンソールで再現されます(これはtee、データストリームを複製するためです)。

どちらを使用するかは、何を達成したいかによって異なります。

2番目のパイプラインの効果を>(のようにutility >output.log 2>&1、標準出力とエラーの両方をファイルに保存するように)だけでは再現できないことに注意してください。teeコンソールと出力ファイルのデータを取得するために使用する必要があります。


その他の注意事項:

最初のコマンドの目に見える効果、

utility 2>&1 >output.log 

と同じだろう

utility >output.log

つまり、標準出力はファイルに送られ、標準エラーはコンソールに送られます。

上記の各コマンドの最後にさらに処理ステップが追加された場合、大きな違いがあります。

utility 2>&1 >output.log | more_stuff

utility >output.log      | more_stuff

最初のパイプラインでmore_stuffは、元の標準エラーストリームをutility標準入力データとして取得しますが、2番目のパイプラインでは、パイプを介して送信されるのは結果の標準出力ストリームのみであるためmore_stuff、パイプラインの一部は何も取得しません標準入力で読み取ります。


コマンド"でutility 2>&1 | tee output.logファイルに書き込まれて、あなたは1以来2も同様で、ティーに向けられていると言うことは意味しています。ティーは、ストリームを複製しているので、出力は両方?だけでなく、コンソール上に表示される間そこで違いutility 2>&1 > output.logutility 2>&1 | tee output.logtee、それは、ストリームを複製することを正しいだろうということ。?
やる気の

例ではutility 2>&1 > output.log | more_stuffutility >ouput.log| more_stuff , is the difference that more_stuff`には、コンソールへの入力として標準エラー出力がありますmore_stuffか?2番目の例では、コンソールへの出力がないため、more_stuff?への入力は本質的にありません。もしそうなら、標準出力がファイルに行き、標準エラーがコンソールに行くことに注意してください。
動機付け

@Motivatedあなたの最初のコメントは私には正しいようです、はい。2番目のコメントに関して:最初のコマンドでmore_stuffは、最初にエラーストリームにutility送信されたもの(ただし、標準出力にリダイレクトされたもの)を受信します。存在しないとコンソールに表示されるためでmore_stuffはなく、標準出力ストリームに送信されるためです。2番目のコマンドでmore_stuffは、パイプラインの左側からの標準出力がないため、何も受け取りません。からのエラーストリームutilityは、2番目のコマンドで引き続きコンソールに表示されます。
クサラナンダ

ありがとう。コマンドutility > output.log | more_stuffは、標準エラーの観点から標準出力ストリームに出力しないため、ということですか?
動機付け

@Motivated左側では標準出力に何も生成されない(リダイレクトされる)ため、パイプを介してデータは送信されません。
クサラナンダ

24

編集メモ

この回答derobert に関するコメントを必ずお読みください


元の答え

2>&1 >output.logは、最初にすべてのファイルハンドル2(標準エラー)をファイルハンドル1(標準出力)送信し、それをfileに送信することを意味しますoutput.log。つまり、標準エラーと標準出力をログファイルに送信します。

2>&1 | tee output.log2>&1ビットと同じで、標準出力と標準エラーを標準出力ストリームに結合します。次に、teeプログラムを介してそれをパイプ処理し、標準入力(などcat)とファイルに標準入力を送信します。そのため、2つのストリーム(エラーと出力)を結合し、それを端末とファイルに出力します。

一番下の行は、最初のファイルがstderr/ stdoutをファイルに送信し、2番目のファイルがファイルと標準出力の両方に送信します(標準出力をリダイレクトする別の構造内にいる場合を除き、おそらく端末です)。

次のようなものを持つことができるので、最後の可能性に言及します。

(echo hello | tee xyzzy.txt) >plugh.txt

ターミナルには何もありません。


13
-1構文の権利はありますが、セマンティクスはありません。実行cat /doesnotexist 2>&1 >output.txt- cat: /doesnotexist: No such file or directory端末にディスプレイが表示され、output.txtが空のファイルになります。優先順位とクロージャの2>&1順序は、(現在の fd1 からdd fd2 )、次に>output.txt(fd1をoutput.txtにリダイレクトし、他は何も変更しない)です。2>&1 |異なる理由は、優先順位:|beforeによるもの>です。
アルケージュ

5
この答えは本質的にあらゆる点で基本的に間違っています。以下の回答の多くは優れていますが、Kusalanandaによるこれは最も明確だと思います。
マイケル・ホーマー

2
@ user14408:UnixとLinuxでアカウントを作成してこの回答を請求した場合は、コメントに対処した後、編集ノートを削除してください。
デロバート

8

最初のコマンドは別のタスクを実行します。

2>&1 > output.log 

古いSTDOUTはSTDERRに保存(コピー)され、STDOUTはファイルにリダイレクトされます。

そのため、stdoutはファイルに移動し、stderrはコンソールに移動します。

そして

 2>&1 | tee output.log

両方のストリームがTにリダイレクトされます。Teeは、その入力をstdout(この場合はコンソール)とファイル(output.log)に複製します。

そして、最初の別の形式があります:

    > output.log  2>&1

これにより、STDOUTとSTDERRの両方がファイルにリダイレクトされます。


4

前者はファイルにのみ出力します。2番目は、ファイル画面の両方に出力します。


4

その理由2>&1 | teeは、stdoutとstderrの両方をログファイルにキャプチャし、同時に画面に表示できるようにするためです。これ>output.txt 2>&1 & tail -fも同様に実行できますが、バックグラウンドコマンドがいつ終了したかはわかりません。プログラムが終了したのか、出力なしで実行されているのか。これ2>&1 | teeはプログラマにとって一般的なイディオムでした。


たとえば、2>&1> file.txtは、stdoutとstderrの両方をfile.txtにキャプチャしないということですか?
動機付け

0

最初にいくつかのサンプルコードを見てみましょう。

#include <stdio.h>
main() 
{
// message 1, on stdout (using  printf)
printf("%s",          "message 1, on stdout (using  printf)\n");

// message 2, on stdout (using fprintf)
fprintf(stdout, "%s", "message 2, on stdout (using fprintf)\n");

// message 3, on stderr (using fprintf)
fprintf(stderr, "%s", "message 3, on stderr (using fprintf)\n");
}

結果を比較してみましょう:
./helloerror
+ファイル:メッセージなし。コンソール:メッセージ1,2,3;

./helloerror >error.txt
+ファイル:メッセージ1,2; コンソール:メッセージ3。

./helloerror 2>&1 >error.txt
+ファイル:メッセージ1,2; コンソール:メッセージ3。
+ ./helloerror> error.txtと同じ

./helloerror >error.txt 2>&1
+ファイル:メッセージ3,1,2; コンソール:メッセージなし。
+順序3が最初、次に1、2の順に注意してください

./helloerror | tee error.txt 2>&1
+ファイル:メッセージ1,2; コンソール:メッセージ3,1,2;
+順序3が最初、次に1、2の順に注意してください

./helloerror 2>&1 | tee error.txt
+ファイル:メッセージ3,1,2; コンソール:メッセージ3,1,2;

使用するには:
./helloerror >error.txt 2>&1
->ファイルにすべての(stdout + stderr)メッセージが必要だが、コンソールにはピントされない場合

./helloerror 2>&1 | tee error.txt
->ファイルにすべての(stdout + stderr)メッセージがあり、コンソールに出力される場合


-1

Unix出力ストリームを要約した投稿は次のとおりです。http//www.devcodenote.com/2015/04/unix-output-streams.html

投稿からの抜粋:

3つの標準出力ストリームがあります。

STDIN - Standard Input - Writes from an input device to the program
STDOUT - Standard Output - Writes program output to screen unless specified otherwise.
STDERR - Standard Error Output - Writes error messages. Also printed to the screen unless specified otherwise.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.