バッチファイルでログローテート

とある、バッチ処理がある。1日に数回、決まった時間に動く。(タスクスケジューラに入っている)
ログの出力は、リダイレクトして追記されてゆく。
特に消去などは考えられていない。と、する。


rem 例えばこういう感じ.bat
echo "毎日これを追記するぞ" >> result.log
こういう感じのバッチファイルが毎日、result.logの量を増やす。
最近のハードディスクの容量が大きいと言えども、消すタイミングがないのはなんとも気持ち悪い。
さて、こういう場合にどう、ログを処分するか。
タスクスケジューラに(時間がかぶらないように)こういうのバッチを入れる。

rem logrotate.bat
ren *.log *.old.log
del *.old.old.old.log
これを一度実行すると

c:\temp\>dir
result.log
c:\temp\>logrotate.bat
c:\temp\>dir
result.old.log
やがて、しかるべき時間が来て、新しいresult.logが作られる。

c:\temp\>dir
result.log result.old.log
c:\temp\>logrotate.bat
c:\temp\>dir
result.old.log result.old.old.log
そしてまた、しかるべき時間が来て、さらに、新しいresult.logが作られる。

c:\temp\>dir
result.log result.old.log result.old.old.log
c:\temp\>logrotate.bat
c:\temp\>dir(一番古いresult.old.old.old.logが消去される)
result.old.log result.old.old.log
当然、この方法が使える場面はresult.logが常にファイルオープンされていない場合のみとなる。
伝統的なUnixプログラミングの世界に習うと、ログローテートのためにプロセスにシグナルを送って、
ログの分離のために、プロセスを一瞬だけ停止したり、とか。やるんだけれど、
そういうプログラムには使えない。
まぁ、それほどでも無いかなと言うときにこの方法はぼちぼち使える。
シェルスクリプトだと、こういう感じか。

#!/bin/sh
ls *.log | sed '/\.log//' | xargs -i mv {}.log {}.old.log
if [ -r *.old.old.old.log ]
then
rm *.old.old.old.log
fi
他にもっとスマートなやり方もいくらでも思いつきそうだが。