受け取るアプリケーションを終了せずにLinux teeコマンドを終了する方法

受け取るアプリケーションを終了せずにLinux teeコマンドを終了する方法

Linuxシステムの電源が入るたびに実行されるbashスクリプトがあります。私は次のように始めます。

( /mnt/apps/start.sh 2>&1 | tee /tmp/nginx/debug_log.log ) &

起動後、私のウィンドウでteeコマンドを見ることができます。メモ出力は以下の通りです。

$ ps | grep tee
  418 root       0:02 tee /tmp/nginx/debug_log.log
3557 root       0:00 grep 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
}

驚くべきことに殺されたティーコマンドはstart.shインスタンスを介しても終了します。なぜこれですか?どうやって終了できますか?ティーコマンドを実行しましたが、start.shはまだ実行されますか?ありがとうございます。

答え1

終了すると、tee指定されたコマンドは、より多くの出力書き込みを試みるまで実行され続けます。その後、リーダーがないパイプに書き込もうとすると、SIGPIPE(ほとんどのシステムでは13個)が受信されます。

SIGPIPEをキャプチャするようにスクリプトを変更し、適切なアクション(出力の書き込みを停止するなど)を行うと、ティーが終了した後も続行できます。


殺すよりも良いtee それでも、logrotate単純化のためにoptionsと一緒に使用されますcopytruncate

見積もりlogrotate(8):

copytruncate

古いログファイルを移動して新しいログファイルを作成することを選択する代わりに、コピーを作成してから元のログファイルを切り捨てます。一部のプログラムでログファイルを閉じるように指示できないため、古いログファイルに永続的に書き込む(追加)できる場合に使用できます。ファイルのコピーとトリミングの間の時間間隔は非常に短いため、一部のロギングデータが失われる可能性があります。このオプションを使用すると、古いログファイルはそのまま残り、作成オプションは適用されません。

答え2

理由を説明してください」

簡単に言うと:書き込みが失敗した場合いいえプログラムが終了し(基本的に)混乱します。考えてみてください。必要な10行をインポートして続行した後、ハードドライブの残りの部分を検索しながら実行したくfind . | head -n 10ないでしょう。findhead

より良い方法:レコーダー内部の回転

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

...ファイルを追加することから始め、内容が100 KBを超えると/tmp/nginx/debug_logファイル名を変更します。/tmp/nginx/debug_log.oldロガー自体が回転を実行するため、回転が発生している間にパイプ破損、エラー、およびデータ損失ウィンドウはありません。すべての行は、あるファイルまたは別のファイルに書き込まれます。

もちろん、これをネイティブbashで実装することは非効率的ですが、上記は例です。上記のロジックを実装できるプログラムがたくさんあります。考慮する:

  • svlogd、Runitファミリーのサービスロガーです。
  • s6-log、スカネットファミリーの積極的に維持されている代替品です。
  • multilogプロセス監督および監視ツールファミリの創設者であるDJB Daemontoolsが提供しています。

関連情報