web-dev-qa-db-ja.com

出力をファイルと標準出力にリダイレクトする方法

Bashでは、fooを呼び出すと、そのコマンドからの出力が標準出力に表示されます。

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

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

798
SCdF

必要なコマンドはteeです。

foo | tee output.file

たとえば、stdoutだけが気になる場合は、次のようにします。

ls -a | tee output.file

標準エラー出力を含めたい場合は、次のようにします。

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

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

さらに、ログファイルにappendを付けたい場合は、tee -aを次のように使用します。

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

2>&1は、標準エラーと標準出力のストリームをダンプします。 tee outfileは取得したストリームを受け取り、それを画面とファイル "outfile"に書き込みます。

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

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

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

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

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

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

<command> |& tee  <outputFile>

gnu bashのマニュアルに示すように

例:

ls |& tee files.txt

「|&」が使用されている場合、 標準出力 に加えてcommand1 標準エラー が、パイプを介してcommand2の標準入力に接続されます。 2>&1の省略形 |です。標準エラーから標準出力へのこの暗黙のリダイレクトは、コマンドで指定されたリダイレクトの後に実行されます。

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

107
tsenapathy

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

ls -lR / | tee -a output.file
16
O.Badr

追加するもの...

パッケージunbufferはFedoraとredhat unixリリースの下でいくつかのパッケージに関するサポート問題を抱えています。

トラブルを回避する

以下は私のために働いた

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

ありがとう ScDFmatthew あなたの入力は私に多くの時間を節約させた..

11
nitinr708

tail -f outputを使うことはうまくいくはずです。

6
Chuck Phillips

このユースケースが私をここに連れてきたので、ボーナスの答え:

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

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

エコーはあなたとして発生し、ファイルの書き込みは「some_user」として発生することに注意してくださいNOTファイルのリダイレクトはあなたのように行われるからです。

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

3
jorfus

< command > |& tee filename#これは、内容としてコマンドステータスを持つファイル "filename"を作成します。ファイルが既に存在する場合、既存の内容を削除してコマンドステータスを書き込みます。

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

画面に "echo"を使って何かを印刷し、そのエコーデータをファイルに追加したい

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

あなたはあなたのスクリプト全体のためにあなたのスクリプトの始めにそのような何かを使うことによってそれをすることができます:

#!/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を使います。
  • 必要なリダイレクトでスクリプトを再起動します。
  • 特別な最初のパラメータ($'string'特別なbash表記で指定された単純なNUL文字)を使用して、スクリプトが再起動されることを指定します(同等のパラメータを元の作業で使用することはできません)。
  • pipefailオプションを使用してスクリプトを再起動するときは、元の終了ステータスを維持するようにしてください。

醜いが、特定の状況では私にとって役に立ちます。

0
Bruno BEAUFILS