目的
そのため、ログが特定のサイズに達したときにログを記録して回転させるスクリプトを作成しました。意図的にログに反映されたエラーと他のコマンドの出力の両方をキャプチャしたいと思います。
これを達成したのは、STDINとSTDOUTをtee
プロセス置換にリダイレクトし、savelog
ログを回転させる小さな関数を書くことでした。
#!/bin/bash
LOGFILE="/var/log/ps.log"
exec > >(tee "$LOGFILE") 2>&1
LOGPATH="/var/log"
MAX_LOGFILE_SIZE=5
rotateLog() {
currentsize=$(du -k $LOGFILE | cut -f1)
if [ $currentsize -ge $MAX_LOGFILE_SIZE ]; then
savelog -dn $LOGFILE &>/dev/null
fi
}
while :; do
echo "A computer program can easily produce gibberish - especially if it has been provided with garbage beforehand. This program does something a little different. It takes a block of text as input and works out the proportion of characters within the text according to a chosen order. For example, an order of 2 means the program looks at pairs of letters, an order of 3 means triplets of letters and so on. The software can regurgitate random text that is controlled by the proportion of characters. The results can be quite surprising."
rotateLog
sleep 5
done
質問
問題は、ps.log
ログが交換された後もps.log.20180829131658
すべてのログが記録されps.log.20180829131658
続け、次のエラーが発生することです。
du: '/var/log/ps.log' にアクセスできません。そのファイルやディレクトリはありません。/ps.sh:行12:[:-ge:単項演算子が必要です。
その結果、ログはもう循環しません!
仮説
ps.log
回転すると、ps.log.20180829131658
新しいログファイルが作成されたとします。しかし、一度だけ実行されるps.log
ので必ずしもそうではありません(exec
ここで正確に何が起こっているのかを説明できる人はいますか?)つまり、スクリプトの先頭にあります。
観察する
>(tee "$LOGFILE")
/var/log/p.log
また、その時点で新しいファイル記述子が作成されますp.log.20180829131658
!これは明らかにログが記録され続ける結果をもたらしますp.log.20180829131658
。誰でもこの動作を説明できますか?
root@b537ccc2c1ab:/var/log# ls -lrt
-rw-r--r-- 1 root root 7248 Aug 29 13:16 ps.log
root@b537ccc2c1ab:/var/log# ls -lrt /proc/*/fd
/proc/8979/fd:
total 0
l-wx------ 1 root root 64 Aug 29 13:16 3 -> /var/log/ps.log
lrwx------ 1 root root 64 Aug 29 13:16 2 -> /dev/pts/17
lrwx------ 1 root root 64 Aug 29 13:16 1 -> /dev/pts/17
lr-x------ 1 root root 64 Aug 29 13:16 0 -> pipe:[3889791]
root@b537ccc2c1ab:/var/log# ls -lrt
-rw-r--r-- 1 root root 11098 Aug 29 13:17 ps.log.20180829131658
root@b537ccc2c1ab:/var/log# ls -lrt /proc/*/fd
/proc/8979/fd:
total 0
l-wx------ 1 root root 64 Aug 29 13:16 3 -> /var/log/ps.log.20180829131658
lrwx------ 1 root root 64 Aug 29 13:16 2 -> /dev/pts/17
lrwx------ 1 root root 64 Aug 29 13:16 1 -> /dev/pts/17
lr-x------ 1 root root 64 Aug 29 13:16 0 -> pipe:[3889791]
このログ記録とログ循環スキームを使用してどのように目標を達成できますか?特に、ログの回転に加えて、スクリプトの他のすべてのコマンドからエラーと出力をキャプチャしながら、私のスクリプトが最新のログファイルに書き込むことができる方法は何ですか?
ベストアンサー1
プロセスによってファイルが開かれると、名前の変更、切り取り、削除など、ファイルに対してさまざまな操作を実行できますが、プロセスはまだファイルを開いています。一般的な間違いは、ログファイルがすべてのディスクスペースを使用すると、人々がスペースを解放するためにファイルを削除することです。ただし、ログファイルに書き込むプロセスはまだ開いているため、スペースは解放されません。ファイルに割り当てられたブロックは、プロセスがファイルを閉じたときにのみ解放されます。 (ここで回避策はファイルを切り取ることです。つまり> logfile
、.)
あなたの場合、ファイルの名前を変更しましたが、ファイルを作成するプロセスはそれを知らないし、気にしません。
ユーティリティにはこのような場合のオプションlogcheck
がありますcopytruncate
。つまり、ログファイルを置き換えられた名前にコピーしてから、元のログファイルを切り捨てます。あなたも同じことができます:
rotateLog() {
currentsize=$(du -k $LOGFILE | cut -f1)
if [ $currentsize -ge $MAX_LOGFILE_SIZE ]; then
ROTATEDLOG=$LOGFILE.$(date +%Y%m%d%H%M%S)
cp -p $LOGFILE $ROTATEDLOG && true > $LOGFILE
fi
}
より良い方法は、ログファイルのクローズや再オープンなどのSIGHUPシグナルを理解するようにプロセスを変更することです。trap
この問題を処理するには、シェルコマンドを参照してください。