この問題の別の形態は、ログが定期的にローテーションされる長時間実行されるアプリケーションで発生します。元のログ(例:)を移動して、mv log.txt log.1実際のロギングが発生する前に同じ名前のファイルですぐに置き換えても、プロセスがファイルを開いたままにしている場合、書き込みが行われますlog.1(まだオープンiノード)または何もない。
これに対処する一般的な方法(システムロガー自体はこの方法で動作します)は、ログを閉じて再度開くシグナルハンドラーをプロセスに実装することです。その後、ログを移動または消去(削除)する場合は、すぐにそのシグナルをプロセスに送信します。
bashの簡単なデモを次に示します-私の酷いシェルスキルは許してください(ただし、ベストプラクティスなどのためにこれを編集する場合は、まず機能を理解し、編集する前にリビジョンをテストしてください)。
#!/bin/bash
trap sighandler INT
function sighandler () {
touch log.txt
exec &> log.txt
}
echo $BASHPID
exec &> log.txt
count=0;
while [ $count -lt 60 ]; do
echo "$BASHPID Count is now $count"
sleep 2
((count++))
done
バックグラウンドに分岐してこれを開始します。
> ./test.sh &
12356
PIDを端末に報告し、ログインを開始することに注意してくださいlog.txt。これで、2分間遊ぶことができます。数秒待ってから試してください:
> mv log.txt log.1 && kill -s 2 12356
kill -2 12356ここでも単純に機能する場合があります。シグナル2はSIGINTです(これはCtrl-Cの機能でもあるため、フォアグラウンドでこれを試して、ログファイルを別の端末から移動または削除できます)trap。チェックする;
> cat log.1
12356 Count is now 0
12356 Count is now 1
12356 Count is now 2
12356 Count is now 3
12356 Count is now 4
12356 Count is now 5
12356 Count is now 6
12356 Count is now 7
12356 Count is now 8
12356 Count is now 9
12356 Count is now 10
12356 Count is now 11
12356 Count is now 12
12356 Count is now 13
12356 Count is now 14
次に、log.txt移動してもまだ書き込み中かどうかを見てみましょう。
> cat log.txt
12356 Count is now 15
12356 Count is now 16
12356 Count is now 17
12356 Count is now 18
12356 Count is now 19
12356 Count is now 20
12356 Count is now 21
中断したところから右に向かっていることに注意してください。記録を残したくない場合は、ログを削除して消去します
> rm -f log.txt && kill -s 2 12356
小切手:
> cat log.txt
12356 Count is now 29
12356 Count is now 30
12356 Count is now 31
12356 Count is now 32
12356 Count is now 33
12356 Count is now 34
12356 Count is now 35
12356 Count is now 36
まだ行っています。
残念ながら、実行されたサブプロセスのシェルスクリプトでこれを実行することはできません。フォアグラウンドにある場合、bashの独自のシグナルハンドラーtrapが中断され、バックグラウンドにフォークした場合、再割り当てできないためです。出力。つまり、これはアプリケーションに実装する必要があるものです。
しかしながら...
アプリケーションを変更できない場合(作成していないなど)、仲介として使用できるCLIユーティリティがあります。また、ログへのパイプとして機能するスクリプトでこの簡単なバージョンを実装することもできます。
#!/bin/bash
trap sighandler INT
function sighandler () {
touch log.txt
exec 1> log.txt
}
echo "$0 $BASHPID"
exec 1> log.txt
count=0;
while read; do
echo $REPLY
done
これを呼び出しましょうpipetrap.sh。次に、ログを記録するアプリケーションを模倣して、テストする別のプログラムが必要です。
#!/bin/bash
count=0
while [ $count -lt 60 ]; do
echo "$BASHPID Count is now $count"
sleep 2
((count++))
done
それはtest.sh:
> (./test.sh | ./pipetrap.sh) &
./pipetrap.sh 15859
これらは、個別のPIDを持つ2つの個別のプロセスです。test.shに集中しているの出力をクリアするにはpipetrap.sh:
> rm -f log.txt && kill -s 2 15859
小切手:
>cat log.txt
15858 Count is now 6
15858 Count is now 7
15858 Count is now 8
15858、test.shがまだ実行中であり、その出力がログに記録されています。この場合、アプリケーションを変更する必要はありません。