次の形式のログファイルがいくつかあります。
log.2014-02-19-10_24_22
つまりlog.YYYY-MM-DD-H24_MI_SS
ログファイルの名前の一部である日付は、ログファイルが最初に作成された日付です。したがって、いつでも次のログファイルをディレクトリに置くことができます。
log.2014-02-19-10_18_54
log.2014-02-19-10_21_20
log.2014-02-19-10_23_11
etc.
これで、cronjobによって呼び出され、「古い」ログファイルを削除するスクリプトができました。
$ cat delete-old-rotated-logs
#!/usr/bin/env bash
find /home/foo -maxdepth 1 -iname log\* -type f -mmin +1800 -exec rm {} \;
私が直面している問題は、ログを記録しているプロセスがクラッシュしたため、「最新の」ログファイルもしばらくして(古いプロセスが書き込まれていないため)「古く」なり、削除されて、トレースが失われることです。 delete-old-rotated-logs
スクリプトを書き直して、最後のファイル(または最後のN
)以外の古いファイルを削除するにはどうすればよいですか?順序付けには、ファイル名自体または変更タイムスタンプ(より堅牢)の両方を使用できます。
find /home/foo -maxdepth 1 -iname log\* -type f -mmin +1800 |
sort | head -n -1 | xargs rm
または、ファイル名の代わりにmtime
を使用する場合:
find /home/foo -maxdepth 1 -iname log\* -type f -mmin +1800 -exec ls -t {} + |
tail -n +2 | xargs rm
@Stephaneのコメントから、より堅牢なアプローチは次のようになります。
IFS=$'\n'
set -f
rm $(
find /home/foo -maxdepth 1 -iname log\* ! -name $'*\n*' -type f -mmin +1800 |
sort | head -n -1 )
またはPOSIXシェルの場合(GNUツールが必要):
IFS='
'
ex_newline='*
*'
set -f
rm $(
find /home/foo -maxdepth 1 -iname log\* ! -name "$ex_newline" -type f -mmin +1800 |
sort | head -n -1 )
GNU sed
/sort
(およびGNU findの最近のバージョンでは、上記のすべてと同様):
find /home/foo -maxdepth 1 -iname log\* -type f -mmin +1800 -print0 |
sort -z | sed -z '$d' | xargs -0 rm
bash
/ksh93
/zsh
:
n=5 # Maximum number of files to keep
cd /home/foo || exit
files=(log.*)
((${#files[@]} <= n)) ||
rm -f -- "${files[@]:0:${#files[@]}-n}"
zsh
を使用すると、次のように簡略化できます。
n=5
rm -f /home/foo/log.*(N[1,-n-1])
また、30時間以上経過したファイルのみを検討する場合は、次のようにします。
n=5
rm -f /home/foo/log.*(Nmh+30[1,-n-1])
POSIXly:
n=5
cd /home/foo || exit
set -- log.*
i=$#
while [ "$i" -gt "$n" ]; do
set -- "$@" "$1"
shift
i=$(($i - 1))
done
shift "$i"
rm -f -- "$@"