Linuxマシンの電源がオンになっている限り実行されるbashスクリプトがあります。以下に示すように開始します。
( /mnt/apps/start.sh 2>&1 | tee /tmp/nginx/debug_log.log ) &
起動後、以下のようにps出力にteeコマンドが表示されます。
$ ps | grep tee
418 root 0:02 tee /tmp/nginx/debug_log.log
3557 root 0:00 grep tee
teeが生成するログのサイズを監視し、ログが特定のサイズに達したときにteeコマンドを強制終了する関数があります。
monitor_debug_log_size() {
## Monitor the file size of the debug log to make sure it does not get too big
while true; do
cecho r "CHECKING DEBUG LOG SIZE... "
debugLogSizeBytes=$(stat -c%s "/tmp/nginx/debug_log.log")
cecho r "DEBUG LOG SIZE: $debugLogSizeBytes"
if [ $((debugLogSizeBytes)) -gt 100000 ]; then
cecho r "DEBUG LOG HAS GROWN TO LARGE... "
sleep 3
#rm -rf /tmp/nginx/debug_log.log 1>/dev/null 2>/dev/null
kill -9 `pgrep -f tee`
fi
sleep 30
done
}
驚いたことに、teeコマンドを強制終了すると、start.shインスタンスによっても強制終了されます。どうしてこれなの? teeコマンドを終了するにはどうすればよいのですか?ありがとう。
tee
が終了すると、それ以上の出力を書き込もうとするまで、それを供給するコマンドは実行を続けます。次に、リーダーなしでパイプに書き込もうとするSIGPIPE(ほとんどのシステムでは13)を取得します。
スクリプトを変更してSIGPIPEをトラップし、適切なアクション(出力の書き込みを停止するなど)を実行すると、ティーが終了した後もスクリプトを続行できるはずです。
tee
を強制終了するよりも、logrotate
をcopytruncate
オプションとともに使用して、シンプル。
引用するにはlogrotate(8)
:
copytruncate
古いログファイルを移動してオプションで新しいログファイルを作成する代わりに、コピーの作成後に元のログファイルを切り捨てます。一部のプログラムにログファイルを閉じるように指示できないため、以前のログファイルに永久に書き込み(追加)し続ける可能性がある場合に使用できます。ファイルのコピーと切り捨ての間に非常に小さなタイムスライスがあるため、一部のログデータが失われる可能性があることに注意してください。このオプションを使用すると、古いログファイルがそのまま残るため、作成オプションは無効になります。
つまり、書き込みが失敗した場合が原因でプログラムが終了した場合(デフォルト)、混乱が生じます。 find . | head -n 10
を検討してください。find
が必要な10行をすでに取得して続行した後、head
が残りのハードドライブをスキャンし続けないようにします。
例として、tee
をまったく使用しない次の例を検討してください。
#!/usr/bin/env bash
file=${1:-debug.log} # filename as 1st argument
max_size=${2:-100000} # max size as 2nd argument
size=$(stat --format=%s -- "$file") || exit # Use GNU stat to retrieve size
exec >>"$file" # Open file for append
while IFS= read -r line; do # read a line from stdin
size=$(( size + ${#line} + 1 )) # add line's length + 1 to our counter
if (( size > max_size )); then # and if it exceeds our maximum...
mv -- "$file" "$file.old" # ...rename the file away...
exec >"$file" # ...and reopen a new file as stdout
size=0 # ...resetting our size counter
fi
printf '%s\n' "$line" # regardless, append to our current stdout
done
次のように実行した場合:
/mnt/apps/start.sh 2>&1 | above-script /tmp/nginx/debug_log
...これは、/tmp/nginx/debug_log
に追加し、100KBを超えるコンテンツが存在する場合にファイルの名前を/tmp/nginx/debug_log.old
に変更することから始まります。ロガー自体がローテーションを行っているため、ローテーションが発生しても、パイプの破損、エラー、データ損失ウィンドウは発生しません。すべての行が1つのファイルまたは別のファイルに書き込まれます。
もちろん、これをネイティブbashに実装することは非効率的ですが、上記は例示的な例です。上記のロジックを実装する多数のプログラムが利用可能です。考慮してください: