Comment conserver: sauvegardes quotidiennes pendant une semaine, hebdomadaires pendant un mois, mensuelles pendant un an et annuelles par la suite


14

J'ai besoin de sauvegarder quotidiennement les données et les fichiers de configuration sur ce serveur. Je dois garder:

  • sauvegardes quotidiennes pendant une semaine
  • sauvegardes hebdomadaires pendant un mois
  • sauvegardes mensuelles pendant un an
  • sauvegardes annuelles après cela

Tout cela accompli via un script shell exécuté quotidiennement à partir de cron.

Voici à quoi devraient ressembler les fichiers de sauvegarde après 10 ans de fonctionnement:

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

9
... ma suggestion normale serait "Utiliser Bacula " (ou un autre logiciel de sauvegarde qui peut gérer la rétention et la rotation pour vous) :-)
voretaq7

1
cette question m'a fait écrire cronicle < github.com/Kraymer/cronicle > parce que la réponse acceptée a le défaut évident de dupliquer les sauvegardes dans les dossiers quotidiens / hebdomadaires / etc. cronicle s'appuie sur des liens symboliques et prend en charge la rotation, supprimant les fichiers sous-jacents lorsqu'aucun dossier ne contient de liens symboliques pointant vers lui.
kraymer

Réponses:


29

Vous êtes sérieusement en train de trop l'ingénierie. Mal.

Voici un pseudocode:

  • Tous les jours:
    • faire une sauvegarde, mettre dans le dailyrépertoire
    • tout supprimer sauf les 7 dernières dailysauvegardes
  • Toutes les semaines:
    • faire une sauvegarde, mettre dans le weeklyrépertoire
    • tout supprimer sauf les 5 dernières weeklysauvegardes
  • Chaque mois:
    • faire une sauvegarde, mettre dans le monthlyrépertoire
    • supprimer tout sauf les 12 dernières monthlysauvegardes
  • Chaque année:
    • faire une sauvegarde, mettre dans le yearlyrépertoire

La quantité de logique que vous devez implémenter est à peu près la même, hein? BAISER.

Cela semble plus simple:

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

Ou, par nombre de fichiers au lieu de l'âge:

s3cmd ls s3://backup-bucket/daily/ | \
    awk '$1 != "DIR"' | \
    sort -r | \
    awk 'NR > 7 {print $4;}' | \
    xargs --no-run-if-empty s3cmd del

En fait, je n'ai pas de répertoires séparés. Il a été écrit pour vider les fichiers dans un compartiment S3. Une fois que tout est au même endroit, la quantité totale de logique que vous devez mettre en œuvre est à peu près la même, peu importe comment vous vous y prenez.
Florin Andrei

5
Ce n'est évidemment pas le cas.
MadHatter

6

Si vous souhaitez simplement conserver, par exemple, 8 sauvegardes quotidiennes et 5 sauvegardes hebdomadaires (tous les dimanches), cela fonctionne comme ceci:

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[@]}

À compter d'aujourd'hui (2014-11-10), cela produira:

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

Comme un exercice qui vous reste, il vous suffit de supprimer tous les fichiers de sauvegarde dont les noms n'apparaissent pas dans le keeptableau.

Si vous souhaitez conserver 13 sauvegardes mensuelles (le premier dimanche de chaque mois) et 6 sauvegardes annuelles (le premier dimanche de chaque année), les choses deviennent un peu plus compliquées:

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[@]}

À compter d'aujourd'hui (2014-11-10), cela produira:

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

Comme ci-dessus, supprimez simplement tous les fichiers de sauvegarde introuvables dans ce tableau.


Nice, et comment faire rm /dir/*.* except keep[@]?
takehin

0

Comme mentionné dans un commentaire, il est généralement préférable de déléguer la tâche de gestion des sauvegardes à un logiciel de gestion des sauvegardes.

Mais voici la logique de bash pour supprimer les anciennes sauvegardes selon vos besoins

#!/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

Code PHP indiquant quels fichiers resteront après avoir fonctionné pendant 3520 jours

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
)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.