O que há de errado com o meu script bash para manter os últimos x arquivos e excluir o resto?

7

Eu tenho este script bash que faz o backup do meu banco de dados em um cronograma:

#!/bin/sh

PT_MYSQLDUMPPATH=/usr/bin
PT_HOMEPATH=/home/philosop
PT_TOOLPATH=$PT_HOMEPATH/philosophy-tools
PT_MYSQLBACKUPPATH=$PT_TOOLPATH/mysql-backups
PT_MYSQLUSER=*********
PT_MYSQLPASSWORD="********"
PT_MYSQLDATABASE=*********
PT_BACKUPDATETIME='date +%s'
PT_BACKUPFILENAME=mysqlbackup_$PT_BACKUPDATETIME.sql.gz
PT_FILESTOKEEP=14

$PT_MYSQLDUMPPATH/mysqldump -u$PT_MYSQLUSER -p$PT_MYSQLPASSWORD --opt $PT_MYSQLDATABASE | gzip -c > $PT_MYSQLBACKUPPATH/$PT_BACKUPFILENAME

Problema com isso é que ele vai continuar jogando os backups na pasta e não limpar arquivos antigos. É aqui que entra a variável PT_FILESTOKEEP . Seja qual for o número, isso é definido como a quantidade de backups que desejo manter. Todos os backups são marcados com tempo, portanto, ao solicitá-los pelo nome, o DESC fornecerá as informações mais recentes primeiro.

Alguém pode me ajudar com o restante do script BASH para adicionar a limpeza de arquivos? Meu conhecimento de bash está faltando e não consigo juntar o código para fazer o resto.

    
por Brady 21.03.2011 / 13:33

6 respostas

9

Primeiro, verifique se você está na pasta correta:

if [ -z $PT_MYSQLBACKUPPATH ]; then
 echo "No PT_MYSQLBACKUPPATH set. Exit"
 exit 1
fi
cd $PT_MYSQLBACKUPPATH
if [ $? != 0 ]; then
 echo "cd to PT_MYSQLBACKUPPATH failed. Exit"
 exit 1
fi

Você pode remover arquivos com mais de n, no seu caso:

find -mtime +14 -delete

Exclui arquivos com mais de 14 dias.

Mais complicada (definitivamente não é ideal, no entanto) solução para sua pergunta:

# Get list of newest files. If newest files are first, use head -n 14 instead of 
# head.
files=('ls | sort | tail -n 14')
# Loop over all files in this folder
for i in *; do 
 preserve=0; 
 #Check whether this file is in files array:
 for a in ${files[@]}; do 
  if [ $i == $a ]; then 
   preserve=1; 
  fi; 
 done; 
 # If it wasn't, delete it (or in this case, print filename)
 if [ $preserve == 0 ]; then 
  echo $i; # test first, then change this to "rm $i"
 fi;
done
    
por 21.03.2011 / 13:40
11

Você pode tentar este:

ls -r1 $PT_MYSQLBACKUPPATH/ | tail -n +$(($PT_FILESTOKEEP+1)) | xargs rm

ls -r1 listará todos os arquivos na ordem inversa, um arquivo por linha.

tail -n +$number filtra os primeiros arquivos $ number-1 da lista (respectivamente. exibe todos os arquivos a partir de $ number até o último).

xargs executará rm com todos os nomes de arquivos da entrada padrão.

    
por 21.03.2011 / 14:08
3

Em relação à resposta do bmk, quando disponível ls -t1 é mais seguro que -r1 (classificar por tempo de modificação em vez de ordem arbitrária de arquivo)

Também em algumas versões da sintaxe tail é tail -n +$number (opção -n é necessária)

Como bônus, combinando ambos, encontrar e ls, aqui está uma maneira de remover arquivos com mais de 30 dias, mas manter pelo menos 15 arquivos:

ls -t1 $PT_MYSQLBACKUPPATH/|tail -n +16| xargs -n1 basename|xargs -n1 -I{} find $PT_MYSQLBACKUPPATH/ -mtime +30 -name {} -delete
    
por 02.06.2013 / 19:31
3

Aqui está o meu uso de inspiração deste post:

#!/bin/bash
# Thu Jun 28 13:22:53 CEST 2012
# ${DESTDIR}/files2keep.sh
# Keep the 3 yungest files
# mra at miracleas.dk , deployed on RHEL 6.
InitValues(){
TODAY='date +"%Y%m%d"'
NOW='date +"%H%M"'
DESTDIR=/mnt/dbdmp
LOGFILE=?{0}-${TODAY}-${NOW}.log
}
BackupFileMaintenance(){
KEEPFILES=('ls -lrt ${DESTDIR}/*mysqldump.sql.gz| tail -n 3| awk '{print $9}'')
    for i in 'ls -lrt ${DESTDIR}/*mysqldump.sql.gz | awk '{print $9}''; do
    preserve=0 
    #Check whether this file is in files array:
        for a in ${KEEPFILES[@]}; do
                if [ $i == $a ]; then
                preserve=1 
                fi 
        done 
    if [ $preserve == 0 ]; then
    echo $i; # then change this to "rm -f $i" after test
    fi
    done
}
InitValues
BackupFileMaintenance
exit
    
por 28.06.2012 / 13:36
0

Desculpe por reabrir este tópico antigo, mas recentemente tive um problema semelhante e não consegui encontrar uma boa solução.

No final, resolvi assim:

cd /directory_where_things_need_removing
ls -tr1dQ * | head -n -31 | xargs rm -rf

partes importantes são ls -tr1dQ, onde as cotações Q resolvem a questão dos espaços, e 1, que dá uma solução por linha. head -n -31 que OMITS as primeiras 31 linhas (no meu caso = 1 mês). por favor, note o - antes de n e antes do número de linhas que você deseja manter. testado em linux científico 6.5

    
por 04.08.2014 / 14:04
-1
ls -t /path/* | grep -v "$(ls -t /path/* | head -6)" | xargs rm -f
    
por 12.08.2013 / 20:15