bashでstderrリダイレクトにテキストを追加する
質問
今、execを使用して、stderrをエラーログにリダイレクトしています
exec 2>> ${errorLog}
唯一の欠点は、execがテキストをログファイルに直接プッシュするだけなので、各タイムスタンプで実行を開始する必要があることです。 stderrをリダイレクトする方法はありますが、タイムスタンプなどのテキストを追加できますか?
解決
これは非常に興味深いです。 bashをよく知っている人に尋ねたところ、彼は次のように言っていました:
foo() { while IFS='' read -r line; do echo "$(date) $line" >> file.txt; done; };
まず、stdinから生の入力を1行読み込む関数を作成しますが、IFSへの割り当てにより空白は無視されません。 1行を読み取った後、適切なデータを先頭に追加して出力します。次に、stderrをその関数にリダイレクトするようにbashに指示する必要があります。
exec 2> >(foo)
stderrに書き込むすべてのものは、foo関数を経由します。対話型シェルで実行すると、プロンプトは表示されなくなります。これは、stderrに出力され、fooの読み取りは行バッファリングされているためです:)
他のヒント
単純に使用できます:
exec 1> >( sed "s/^/$(date '+[%F %T]'): /" | tee -a ${LOGFILE}) 2>&1
これは、プロンプトが表示されないという問題を完全には解決しません(パイプはデータをキャッシュするため、短時間で表示されますが、リアルタイムでは表示されません...)。ファイル内にも。
唯一の問題は、私が解決できなかったことです、これは関数からこれを行うことです、それはサブシェルを開くので、execはメインプログラムにとって役に立たない...
この例では、元のstdoutとstderrを失うことなく、stdoutとstderrをリダイレクトします。また、stdoutハンドラーのエラーはstderrハンドラーに記録されます。ファイル記述子は変数に保存され、子プロセスで閉じられます。 Bashは、衝突が発生しないように注意します。
#! /bin/bash
stamp ()
{
local LINE
while IFS='' read -r LINE; do
echo "$(date '+%Y-%m-%d %H:%M:%S,%N %z') $ $LINE"
done
}
exec {STDOUT}>&1
exec {STDERR}>&2
exec 2> >(exec {STDOUT}>&-; exec {STDERR}>&-; exec &>> stderr.log; stamp)
exec > >(exec {STDOUT}>&-; exec {STDERR}>&-; exec >> stdout.log; stamp)
for n in $(seq 3); do
echo loop $n >&$STDOUT
echo o$n
echo e$n >&2
done
これには現在のBashバージョンが必要ですが、 Shellshock のおかげで信頼できますこれは最近です。
私はちょうど同じ小さな端正なものを探していました。この投稿を見た後、私も有望に見える別のアプローチを見ました: http: //utcc.utoronto.ca/~cks/space/blog/unix/PipingJustStderr
cat q23123 2> tmp_file ;cat tmp_file | sed -e "s/^/$(date '+[%F %T]'): /g" >> output.log; rm -f tmp_file