exclui arquivos de log antigos, exceto o último (classificado alfanumericamente)

4

Eu tenho vários arquivos de log no formulário:

log.2014-02-19-10_24_22

Ou seja. log.YYYY-MM-DD-H24_MI_SS

A data que faz parte do nome do arquivo de log é quando o arquivo de log foi criado pela primeira vez. Então, a qualquer momento, posso ter os seguintes arquivos de log no meu diretório:

log.2014-02-19-10_18_54
log.2014-02-19-10_21_20
log.2014-02-19-10_23_11
etc.

Agora eu tenho um script que é invocado por um cronjob e exclui arquivos de log "antigos":

$ cat delete-old-rotated-logs 
#!/usr/bin/env bash
find /home/foo -maxdepth 1 -iname log\* -type f -mmin +1800 -exec rm {} \;

O problema que estou enfrentando é que às vezes o processo que está log travando, então o arquivo de log "mais recente" também fica "velho" depois de algum tempo (já que nenhum processo está escrevendo nele) e é deletado, perdendo assim o rastreio . Como posso reescrever o script delete-old-rotated-logs para que ele exclua arquivos antigos, exceto o último (ou o último N )? Para o ordenamento, pode-se usar tanto o nome do arquivo como o registro de data e hora da modificação (mais robusto).

    
por Marcus Junius Brutus 19.02.2014 / 12:14

2 respostas

3
find /home/foo -maxdepth 1 -iname log\* -type f -mmin +1800 |
  sort | head -n -1 | xargs rm

Ou se você quiser usar mtime em vez do nome do arquivo:

find /home/foo -maxdepth 1 -iname log\* -type f -mmin +1800 -exec ls -t {} + |
  tail -n +2 | xargs rm

A partir dos comentários do @Stephane, uma abordagem mais robusta seria:

IFS=$'\n'
set -f
rm $(
  find /home/foo -maxdepth 1 -iname log\* ! -name $'*\n*' -type f -mmin +1800 |
  sort | head -n -1 )

Ou para o shell POSIX (ainda requer ferramentas 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 )

Um único pipeline (robusto) pode ser usado com uma versão recente do GNU sed / sort (e o GNU encontra com todos os itens acima):

find /home/foo -maxdepth 1 -iname log\* -type f -mmin +1800 -print0 |
  sort -z | sed -z '$d' | xargs -0 rm
    
por 19.02.2014 / 12:24
2

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}"

Com zsh , pode ser simplificado para:

n=5
rm -f /home/foo/log.*(N[1,-n-1])

E se você quiser considerar apenas os arquivos com mais de 30 horas:

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 -- "$@"
    
por 19.02.2014 / 13:08

Tags