出力をファイルおよびstdoutにリダイレクトする方法


989

bashでは、呼び出しfooにより、そのコマンドからの出力がstdoutに表示されます。

呼び出しfoo > outputは、そのコマンドからの出力を指定されたファイル(この場合は「出力」)にリダイレクトします。

ファイルへのリダイレクトを出力する方法はありますし、それが標準出力に表示がありますか?


3
エラー出力をファイルにキャプチャするために探している人がいる場合は、-unix.stackexchange.com/questions/132511/…
Murphy

2
用語に関する注記:実行するとfoo > output、データ stdoutに書き込まれ、stdout というファイルですoutput。つまり、ファイルへの書き込みがされて標準出力への書き込み。stdoutと端末の両方に書き込むことができるかどうかを尋ねています。
ウィリアムパーセル

2
@WilliamPursell私はあなたの説明が物事を改善すると確信していません:-)これはどうですか:OPは、呼び出されたプログラムの stdoutをファイルと呼び出しプログラムの stdout(後者は呼び出されたプログラムが行う stdoutの両方)に送ることができるかどうかを尋ねています特別な処理が行われなかった場合は継承します(つまり、呼び出し側プログラムがインタラクティブbashセッションの場合はターミナル)。また、呼び出されたプログラムのstderrも同様に指示したい場合もあります(「そのコマンドからの出力」は、stderrを含めることを意味すると合理的に解釈される場合があります)。
Don Hatch、

回答:


1380

必要なコマンドの名前はtee次のとおりです。

foo | tee output.file

たとえば、stdoutのみに関心がある場合:

ls -a | tee output.file

stderrを含めたい場合は、次のようにします。

program [arguments...] 2>&1 | tee outfile

2>&1チャネル2(stderr /標準エラー)をチャネル1(stdout /標準出力)にリダイレクトし、両方がstdoutとして書き込まれるようにします。また、指定された出力ファイルにも送信されます。teeコマンドの。

さらに、ログファイルに追加する場合は、次のように使用tee -aします。

program [arguments...] 2>&1 | tee -a outfile

173
OPが「すべての出力」のリダイレクトを希望する場合は、stderrも取得する必要があります。「ls -lR / 2>&1 | tee output.file」
James Brady

45
@evanmcdonnal答えは間違っていません、それはあなたの要件に応じて十分に具体的でないか、完全ではないかもしれません。確かに、ファイルに保存される出力の一部としてstderrを望まない可能性がある状況があります。5年前に私がこれに答えたとき、彼は投稿の件名でstdoutについて言及していたので、OPはstdoutだけが必要だと思いました。
Zoredache 2014年

3
申し訳ありませんが、少し混乱していました。試してみたところ、何も出力されませんでした。おそらく、すべてがstderrになるでしょう。
evanmcdonnal 2014年

38
-a引数を使用しteeてコンテンツを追加しますoutput.file代わりにそれを上書きする、:ls -lR / | tee -a output.file
kazy

16
$?後で使用している場合は、ステータスコードが返されteeます。代わりに、を使用できます${PIPESTATUS[0]}
LaGoutte

501
$ program [arguments...] 2>&1 | tee outfile

2>&1stderrとstdoutストリームをダンプします。 tee outfile取得したストリームを取得して、画面とファイル「outfile」に書き込みます。

これはおそらくほとんどの人が探しているものです。考えられる状況は、一部のプログラムまたはスクリプトが長時間懸命に働いており、大量の出力を生成していることです。ユーザーは定期的に進行状況を確認したいが、出力をファイルに書き込むことも望んでいる。

問題(特にstdoutとstderrストリームを混合する場合)は、プログラムによってフラッシュされるストリームに依存していることです。たとえば、stdoutへのすべての書き込みがフラッシュされないが、stderrへのすべての書き込みフラッシュされる場合、それらは出力ファイルと画面上で時系列順ではなくなります。

また、プログラムが進行状況を報告するために数分ごとに1行または2行しか出力しない場合も問題があります。このような場合、プログラムによって出力がフラッシュされなかった場合、何時間もパイプを介してプッシュされないため、ユーザーは何時間も画面に出力を見ることはありません。

更新:パッケージのunbuffer一部であるプログラムはexpect、バッファリングの問題を解決します。これにより、stdoutとstderrはすぐに画面とファイルに書き込み、結合してにリダイレクトされたときに同期を保ちますtee。例えば:

$ unbuffer program [arguments...] 2>&1 | tee outfile

7
だれかがosxの「アンバッファー」を知っていますか?
John Mee

7
unbufferを使用できない場合、GNU coreutilsにはstdbuffと呼ばれるツールが含まれています。このツールを使用すると、出力のバッファリングを防止できます$ stdbuf -o 0 program [arguments...] 2>&1 | tee outfile
Peter

1
OS Xを使用している場合、ほとんどの場合、unbufferを使用する方がわずかに簡単ですが、実行中のコマンドにシグナルを渡したい場合はそうではありません。私のコメントは、coreutilsがデフォルトでインストールされる可能性が最も高いLinuxを使用しているユーザーを対象としています。あなたがstdbuf構文について混乱している場合@Ethan、この回答を参照してください。stackoverflow.com/a/25548995/942781
ピーター・

3
pythonは、-u出力のバッファリングを解除する組み込みオプションがあります。
fabian789

1
追加のコードなしでログを記録するだけでなく、実行にかかる時間/日にわたって出力を確認したいMLモデルのトレーニングのための絶対的な命の恩人、ありがとう!
rococo

126

私のために働くもう一つの方法は、

<command> |& tee  <outputFile>

GNU bashのマニュアルに示されているように

例:

ls |& tee files.txt

'|&'を使用すると、command1の標準エラーは標準出力に加えて、パイプを介してcommand2の標準入力に接続されます。それがある2>&1のための速記 |。この標準エラーから標準出力への暗黙的なリダイレクトは、コマンドで指定されたリダイレクトの後に実行されます。

詳細については、リダイレクトを参照してください。


10
$?後で使用している場合は、ステータスコードが返されteeます。代わりに、を使用できます${PIPESTATUS[0]}
LaGoutte 2017

1
このメソッドは、色付きのコンソール出力を破棄します。
shakram02

試してみてください:unbuffer ls -l --color = auto | tee files.txt
Luciano Andress Martini

17

主にZoredache ソリューションを使用できますが、出力ファイルを上書きしたくない場合は、次のように-aオプションを使用してteeを記述してください。

ls -lR / | tee -a output.file

11

追加するもの...

パッケージunbufferには、fedoraおよびredhat unixリリースでの一部のパッケージに関するサポート問題があります。

トラブルを別にして

次は私のために働いた

bash myscript.sh 2>&1 | tee output.log

ありがとうSCDFをマシューあなたの入力は多くの時間の私を救いました。..



3

このユースケースが私をここにもたらしたので、ボーナス回答:

他のユーザーとしてこれを行う必要がある場合

echo "some output" | sudo -u some_user tee /some/path/some_file

あなたと、ファイルの書き込みがどうなるか「some_user」として起こりますよう、エコーが発生することに注意してくださいませ、ファイルのリダイレクトが発生しますので、「some_user」としてエコーを実行し、>>「some_file」で出力をリダイレクトした場合の仕事がありますあなたとして。

ヒント:teeは-aフラグ付きの追加もサポートしています。別のユーザーとしてファイル内の行を置き換える必要がある場合は、目的のユーザーとしてsedを実行できます。


2

< command > |& tee filename #これにより、コマンドステータスをコンテンツとして含むファイル「filename」が作成されます。ファイルがすでに存在する場合は、存在するコンテンツが削除され、コマンドステータスが書き込まれます。

< command > | tee >> filename #これはファイルにステータスを追加しますが、コマンドのステータスをstandard_output(画面)に出力しません。

画面で「エコー」を使用して何かを印刷し、そのエコーデータをファイルに追加したい

echo "hi there, Have to print this on screen and append to a file" 

1

スクリプトの最初にそのようなものを使用することにより、スクリプト全体に対してそれを行うことができます。

#!/usr/bin/env bash

test x$1 = x$'\x00' && shift || { set -o pipefail ; ( exec 2>&1 ; $0 $'\x00' "$@" ) | tee mylogfile ; exit $? ; }

# do whaetever you want

これにより、stderrとstdoutの両方の出力が呼び出されたファイルにリダイレクトされmylogfile すべてが同時に stdout 送られます。

それはいくつかの愚かなトリックが使用されています:

  • 使用execセットアップリダイレクトにコマンドなしで、
  • tee出力を複製するために使用し、
  • 必要なリダイレクトでスクリプトを再起動し、
  • 特別な最初のパラメーター(特別なbash表記でNUL指定された単純な文字$'string')を使用して、スクリプトの再起動を指定します(元の作業では同等のパラメーターを使用できません)。
  • pipefailオプションを使用してスクリプトを再起動するときに、元の終了ステータスを維持しようとします。

醜いですが、特定の状況で私にとっては便利です。


-13

Tシャツはこれに最適ですが、これでも機能します

ls -lr / > output | cat output

10
これは、出力がまだ存在せず、必要な動作を行わない場合はエラーになります。全体的に無意味です。たぶん、あなたは「;」を意味しました 「|」の代わりに ?
Robert Gamble、

6
を使用した場合でも;、遅いコマンドの間は出力が大幅に遅延します。
Brad Koch
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.