Bashでは、foo
を呼び出すと、そのコマンドからの出力が標準出力に表示されます。
foo > output
を呼び出すと、そのコマンドからの出力は指定されたファイル(この場合は 'output')にリダイレクトされます。
出力をファイルにリダイレクトする方法はありますか - そして それを標準出力に表示しますか?
必要なコマンドは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
$ 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
私のために働くもう一つの方法は、
<command> |& tee <outputFile>
例:
ls |& tee files.txt
「|&」が使用されている場合、 標準出力 に加えてcommand1 標準エラー が、パイプを介してcommand2の標準入力に接続されます。 2>&1の省略形 |です。標準エラーから標準出力へのこの暗黙のリダイレクトは、コマンドで指定されたリダイレクトの後に実行されます。
詳しくは、 リダイレクト を参照してください。
tail -f output
を使うことはうまくいくはずです。
このユースケースが私をここに連れてきたので、ボーナスの答え:
他のユーザーとしてこれを行う必要がある場合
echo "some output" | Sudo -u some_user tee /some/path/some_file
エコーはあなたとして発生し、ファイルの書き込みは「some_user」として発生することに注意してくださいNOTファイルのリダイレクトはあなたのように行われるからです。
ヒント:teeは、-aフラグを使用した追加もサポートしています。ファイル内の行を別のユーザーとして置き換える必要がある場合は、目的のユーザーとしてsedを実行できます。
< 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"
あなたはあなたのスクリプト全体のためにあなたのスクリプトの始めにそのような何かを使うことによってそれをすることができます:
#!/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
オプションを使用してスクリプトを再起動するときは、元の終了ステータスを維持するようにしてください。醜いが、特定の状況では私にとって役に立ちます。