Como manter: backups diários por uma semana, semanalmente por um mês, mensalmente por um ano e anualmente depois disso

14

Preciso fazer backup de dados e arquivos de configuração neste servidor, diariamente. Eu preciso manter:

  • backups diários por uma semana
  • backups semanais por um mês
  • backups mensais por um ano
  • backups anuais depois disso

Tudo isso realizado através de um script de shell executado diariamente a partir do cron.

É assim que os arquivos de backup devem aparecer após 10 anos de execução:

blog-20050103.tar.bz2
blog-20060102.tar.bz2
blog-20070101.tar.bz2
blog-20080107.tar.bz2
blog-20090105.tar.bz2
blog-20100104.tar.bz2
blog-20110103.tar.bz2
blog-20120102.tar.bz2
blog-20130107.tar.bz2
blog-20130902.tar.bz2
blog-20131007.tar.bz2
blog-20131104.tar.bz2
blog-20131202.tar.bz2
blog-20140106.tar.bz2
blog-20140203.tar.bz2
blog-20140303.tar.bz2
blog-20140407.tar.bz2
blog-20140505.tar.bz2
blog-20140602.tar.bz2
blog-20140707.tar.bz2
blog-20140728.tar.bz2
blog-20140804.tar.bz2
blog-20140811.tar.bz2
blog-20140816.tar.bz2
blog-20140817.tar.bz2
blog-20140818.tar.bz2
blog-20140819.tar.bz2
blog-20140820.tar.bz2
blog-20140821.tar.bz2
blog-20140822.tar.bz2
Florin Andrei
fonte
9
... a minha sugestão normal seria "Use Bacula " (ou algum outro software de backup que pode lidar com a retenção e rotação para você) :-)
voretaq7
1
essa pergunta me fez escrever cronicle < github.com/Kraymer/cronicle > porque a resposta aceita tem o defeito óbvio de duplicar backups nas pastas diária / semanal / etc. O cronicle conta com links simbólicos e cuida da rotação, excluindo arquivos subjacentes quando nenhuma pasta contém links simbólicos apontando para ele.
kraymer

Respostas:

29

Você está seriamente projetando demais isso. Seriamente.

Aqui estão alguns pseudocódigo:

  • Todo dia:
    • faça um backup, coloque no dailydiretório
    • remova tudo, exceto os últimos 7 dailybackups
  • Toda semana:
    • faça um backup, coloque no weeklydiretório
    • remova tudo, exceto os últimos 5 weeklybackups
  • Todo mês:
    • faça um backup, coloque no monthlydiretório
    • remova tudo, exceto os últimos 12 monthlybackups
  • Todo ano:
    • faça um backup, coloque no yearlydiretório

A quantidade de lógica que você precisa implementar é a mesma, não é? BEIJO.

Parece mais fácil:

s3cmd ls s3://backup-bucket/daily/ | \
    awk '$1 < "'$(date +%F -d '1 week ago')'" {print $4;}' | \
    xargs --no-run-if-empty s3cmd del

Ou, pela contagem de arquivos em vez da idade:

s3cmd ls s3://backup-bucket/daily/ | \
    awk '$1 != "DIR"' | \
    sort -r | \
    awk 'NR > 7 {print $4;}' | \
    xargs --no-run-if-empty s3cmd del
MikeyB
fonte
Na verdade, não tenho diretórios separados. Foi gravado para despejar arquivos em um bucket S3. Quando tudo estiver em um só lugar, a quantidade total de lógica que você precisa implementar é a mesma, não importa como você a faça.
Florin Andrei
5
Evidentemente não é.
21914 MadHatter
6

Se você deseja apenas manter, por exemplo, 8 backups diários e 5 backups semanais (todos os domingos), funciona assim:

for i in {0..7}; do ((keep[$(date +%Y%m%d -d "-$i day")]++)); done
for i in {0..4}; do ((keep[$(date +%Y%m%d -d "sunday-$((i+1)) week")]++)); done
echo ${!keep[@]}

A partir de hoje (10/11/2014), isso produzirá:

20141012 20141019 20141026 20141102 20141103 20141104
20141105 20141106 20141107 20141108 20141109 20141110

Como exercício deixado para você, você só precisa excluir todos os arquivos de backup cujos nomes não aparecem no keeparray.

Se você deseja manter 13 backups mensais (primeiro domingo de cada mês) e 6 backups anuais (primeiro domingo de cada ano), as coisas ficam um pouco mais complicadas:

for i in {0..7}; do ((keep[$(date +%Y%m%d -d "-$i day")]++)); done
for i in {0..4}; do ((keep[$(date +%Y%m%d -d "sunday-$((i+1)) week")]++)); done
for i in {0..12}; do
        DW=$(($(date +%-W)-$(date -d $(date -d "$(date +%Y-%m-15) -$i month" +%Y-%m-01) +%-W)))
        for (( AY=$(date -d "$(date +%Y-%m-15) -$i month" +%Y); AY < $(date +%Y); AY++ )); do
                ((DW+=$(date -d $AY-12-31 +%W)))
        done
        ((keep[$(date +%Y%m%d -d "sunday-$DW weeks")]++))
done
for i in {0..5}; do
        DW=$(date +%-W)
        for (( AY=$(($(date +%Y)-i)); AY < $(date +%Y); AY++ )); do
                ((DW+=$(date -d $AY-12-31 +%W)))
        done
        ((keep[$(date +%Y%m%d -d "sunday-$DW weeks")]++))
done
echo ${!keep[@]}

A partir de hoje (10/11/2014), isso produzirá:

20090104 20100103 20110102 20120101 20130106 20131103
20131201 20140105 20140202 20140302 20140406 20140504
20140601 20140706 20140803 20140907 20141005 20141012
20141019 20141026 20141102 20141103 20141104 20141105
20141106 20141107 20141108 20141109 20141110

O mesmo que acima, exclua todos os arquivos de backup não encontrados nesta matriz.

Pow Pow
fonte
Legal, e como eu faço rm /dir/*.* except keep[@]?
takeshin
0

Conforme mencionado em um comentário, normalmente é melhor delegar a tarefa de gerenciar backups em um software de gerenciamento de backup.

Mas aqui está a lógica no bash para excluir backups mais antigos conforme sua necessidade

#!/bin/sh

delete() {
    echo "Deleting $1"
}

DOW=$(date +%u)

if [ $DOW -eq 1 ]; then
    DATE_DAY=$(date -d "-28 days" +"%d")
    if [ $DATE_DAY -gt 7 ]; then
        DATE=$(date -d "-28 days" +"%Y-%m-%d")
        delete $DATE
    fi

    DATE_DAY=$(date -d "-364 days" +"%d")
    DATE_MONTH=$(date -d "-364 days" +"%m")
    if [ $DATE_DAY -le 7 ] && [ $DATE_MONTH -gt 1 ]; then
        DATE=$(date -d "-364 days" +"%Y-%m-%d")
        delete $DATE
    fi
else
    DATE=$(date -d "-7 days" +"%Y-%m-%d")
    delete $DATE
fi

Código PHP mostrando quais arquivos permanecerão após a execução por 3520 dias

https://ideone.com/n2ymQy

Array
(
    [0] => 2005-01-03
    [1] => 2006-01-02
    [2] => 2007-01-01
    [3] => 2008-01-07
    [4] => 2009-01-05
    [5] => 2010-01-04
    [6] => 2011-01-03
    [7] => 2012-01-02
    [8] => 2013-01-07
    [9] => 2013-09-02
    [10] => 2013-10-07
    [11] => 2013-11-04
    [12] => 2013-12-02
    [13] => 2014-01-06
    [14] => 2014-02-03
    [15] => 2014-03-03
    [16] => 2014-04-07
    [17] => 2014-05-05
    [18] => 2014-06-02
    [19] => 2014-07-07
    [20] => 2014-07-28
    [21] => 2014-08-04
    [22] => 2014-08-11
    [23] => 2014-08-16
    [24] => 2014-08-17
    [25] => 2014-08-18
    [26] => 2014-08-19
    [27] => 2014-08-20
    [28] => 2014-08-21
    [29] => 2014-08-22
)
Joyce Babu
fonte