# [script] savoir si un fichier à été backupé

## loopx

Bonjour, 

Je suis entrain de faire un script de backup (heu, stage4?) de mon système. Le principe est qu'il devra être lancé par cron tout les X temps (X n'a rien avoir avec la fréquence de backup). Considéront 1 fichier archive, celui-ci est créé toute les semaines via le script. Si le fichier dépasse 1 semaine d'age, il faut recréé l'archive (donc, backup total toute les semaines et je prévois de garder 2 archives => 2 semaines).

J'ai fais un petit bout de script, mais il faudrait maintenant ajouter un petit "if" qui ira tester la date de l'archive avec la date courante ... et plus précisément, savoir si l'archive à plus ou moins d'une semaine.

Avec "find", on peut faire des trucs cool, mais la, je n'utilise pas find ... (il y a -mtime X ou X est un nombre de jour). Genre, si un fichier à été modifié il y a 101 jour, le fichier à plus que 100 jours et donc, je peux le supprimer (c'est ainsi que je supprime les archives trop ancienne).

Tout est basé sur la date du système qui est toujours correct.

Une idée ?

```

DATE=`date '+%Y%m%d'`

BACKUP_DIR="/mnt/data2/backup/system"

for DIR in bin boot etc home lib opt root sbin usr var

do

        #check if backup already made

        ???????

        #backup to an other disk

        tar cvfz $BACKUP_DIR/system-$DIR-$DATE.tar.gz /$DIR

done

```

Merci d'avance

----------

## truc

si ça peut t'aider tu peux mettre la date sous cette forme

```
CURDATE=$(date +''%Y%m%d')
```

et tu peux aussi avoir la date d'il y a 10 jours:

```
PREVDATE=$(date +'%Y%m%d'  -d '-10 days')
```

Et après, tu peux faire des opérations arithmétique dessus, style, tu récupère la date de ton backup, tu la compare à PREVDATE (un simple < $PREVDATE devrait faire l'affaire..)

Bref, tu brodes quoi... 

ça t'aide?

----------

## loopx

Merci, ca m'aide, je connaissais pas cette possibilité avec "date". J'ai trouvé un autre truc qui sera peut être plus "portable" (unix) :

```

DATE=`date '+%Y%m%d'`

BACKUP_DIR="/mnt/data2/backup/system"

let INTERVAL=1*60*60*24*7       #=1 week

let DATE_TEST=`date +%s`-$INTERVAL

for DIR in bin boot etc home lib opt root sbin usr var

do

        #check if backup already made

        if [ $DATE_TEST -le `stat -c %Y a.txt` ]

                ????????

        #backup to an other disk

        tar cvfz $BACKUP_DIR/system-$DIR-$DATE.tar.gz /$DIR

done

```

En gros, j'ai pris les secondes après epoch pour travailler et j'ai calculé moi meme que 1 semaine = .. (voir script)  :Very Happy:       c'est moins propre, mais ptet plus portable non ?

Sinon, je vais noter ta soluce dans mon wiki aussi  :Wink: 

La, je bloque ... Je bloque car le if, il utilise "a.txt" qui est en réalité un fichier avec un nom quelconque (car la date est incluse dans le nom de fichier) et surtout, car il peut y avoir plusieurs archive d'un meme répertoire! (2 par défaut).

Il faut maintenant que je remplace le "a.txt" par une recherche dans le répetoire en question et en utilisant un masque (*etc*) pour chopper les archives du répertoires ... et aussi trier par date (-t) ET enfin, sélectionner le fichier ... et ca je sais pas comment faire :s. Je suis arrivé à ceci :

```

loop test # ls

a.txt  test.sh

loop test # ls -t

test.sh  a.txt

=> try to select "test.sh" ...

```

Donc, "test.sh" est plus récent .. et donc, après le LS, il faut que je chope le premier fichier (qui ne contient aucun caractère spécial et qui est le plus récent) ... Une idée ?

----------

## Enlight

je suis pas sur d'avoir tout compris mais voilà ce queje pense avoir retenu.

- Ton archive s'appelera foo-${date}.tbz ou quoique ce soit d'autre comme extension.

- La date inclue dans le nom est la date à laquelle l'archive est crée.

- Seules les archives sont enregistrées dans ce répertoire.

- Ajouter un fichier dans un répertoire modifie le répertoire.

En conséquence le mtime du répertoire (accesible via stat ou ls) est directement lié au nom de la dernière archive.

Edit : soluce 2 dans le cas d'un ls trié (oui j'ai relu entre temps)

```
counter = 0

for i in `ls -t $mydir`;

do counter += 1; # je sais même plus si ça passe en bash ça

case counter in

1)

file = $i;;

*);;

esac;

done;;
```

c'est probablement truffé de fautes de syntaxe mais l'idée y est   :Wink: 

----------

## loopx

- 1 répertoire d'archive

- qui peut contenir 1 ou plusieurs archive "de même nom" (ici: etc => etc-ladate.tgz etc-ladate2.tgz etc ...)

- je veux récupérer le nom du fichier le plus récent selon le nom d'archive => si "etc", alors prendre le "etc-ladate2.tgz

Je me souviens du "for .. in ..." qui peut être utile, mais étant donné que cette récupération de nom de fichier est "statique" (dans le sens ou on prendra 1 seul fichier), il est inutile d'utiliser la boucle "for" ou toute autre boucle ... n'y a t'il pas une commande pour récupérer juste la première chaine ? (pour faire plus propre qu'une boucle + switch) ??? (et le résultat de "ls", il est toujours sur 1 ligne si il y a mille résultat ? je suppose que oui, elle est juste très longue).

----------

## Magic Banana

Je viens de pondre cela :

```
#!/bin/sh

BACKUP_DIR="/mnt/data2/backup/system"

DAYS_DELAY=7

toBackup ()

{

    if [ -f "$BACKUP_DIR/$file" ]

    then

   currentDate=`ls -og --time-style="+%Y%m%d" "$file"`

   currentDate=${currentDate# }

   currentDate=${currentDate# }

   backupDate=`ls -og --time-style="+%Y%m%d" "$BACKUP_DIR/$file"`

   backupDate=${backupDate# }

   backupDate=${backupDate# }

   return [ ${backupDate%% } -gt `date --date="${currentDate%% } -$DAYS_DELAY days"` ]

    fi

    return 0

}

for file in $*

do

    if [ -d "$file" ]

    then

   "$0" "$file/*"

    elif toBackup

    then

   mkdir -p "$BACKUP_DIR/${file%/}"

   cp "$file" "$BACKUP_DIR/$file"

    fi

done
```

Bon, je ne l'ai pas beaucoup testé (il faudrait que je dorme quand même !  :Laughing:  ) mais ça devrait le faire. Tu appelles le script avec tous les fichiers (typiquement des répertoires) à sauvegarder. En tout cas cela me paraît plus propre que ce dans quoi tu t'es lancé (j'aurais toutefois aimé une commande pour ne sortir QUE la date d'un fichier mais je n'ai pas trouvée...).

----------

## loopx

J'ai trouvé ce qu'il me faut ... :

```

awk '{print $1}'

```

avant, il y aura le ls suivit d'un pipe. Je testerais demain, faut aussi que je dorme  :Smile: 

----------

## loopx

awk va pas, quand on utilise ls pipe, il place tout en colonne et non en ligne (donc, j'ai plein de ligne et pas plein de colonne).

J'ai trouvé ceci :

```

loop bin # ls /usr/bin | sed -n "1 P"

[

```

Ca fonctionne avec "sed" mais je comprend pas du tout la différence entre le "p" et le "P" .... si quelqu'un sais m'aider :s

EDIT: voilà ou j'en suis :

```

serveur script # cat backup-system.sh

#! /bin/sh

# by loopx

# 20081209

##########

DATE=`date '+%Y%m%d'`

BACKUP_DIR="/mnt/data2/backup/system"

let INTERVAL=1*60*60*24*7       #one week

let DATE_TEST=`date +%s`-$INTERVAL      #date used to test age of archives

for DIR in bin boot etc home lib opt root sbin usr var

do

        #select most recent archive of a gived directory

        lastBackupFile=`ls -t $BACKUP_DIR/*-$DIR-*.tar.gz | sed -n "1 p"`

        #check old arhive; do backup if most recent archive is not valid or is too old

        if [[ ! -f $lastBackupFile || $DATE_TEST -gt `stat -c %Y $lastBackupFile` ]]

        then

                echo "> doing backup of $DIR"

                #backup to an other disk

                tar cvfz $BACKUP_DIR/system-$DIR-$DATE.tar.gz /$DIR

        fi

done

```

Ce script va donc faire des backup si et seulement si il n'y a pas d'archive ou si l'archive a plus d'une semaine.

Il faut encore faire plein de truc mais bon, ce sera une autre hisotire  :Wink: 

Ce script sera aussi utilisé par nagios pour vérifier si les backup ont été réalisée, si elle ne sont pas périmée (car plus de place par exemple) ou si les archive n'ont pas été répliquée ailleur (car je vais envoyer ca via ftp à d'autre machine pour assurer que l'archive ne soit pas perdue betement car une seule copie).

----------

## xaviermiller

find, avec l'option "-newer" donne tous les fichiers plus récents qu'un fichier donné (ton dernier tar de backup en l'occurence, ou un fichier timestamp daté de quelques minutes avant le tar)

et tar a une option "upgrade", qui n'ajoute que les nouveaux fichiers. Vu que tar EST le logiciel d'archivage sur cassette, autant l'utiliser simplement  :Wink: 

----------

## kwenspc

oui et avec tar tu peux aussi exclure certains rep/fichiers très facilement. Du coup pas besoin de faire une archive de chaque rep mais directement de l'ensemble (sans les rep exclus). Donc tu vires ta boucle for et zou.

----------

## truc

```
ls /usr/bin | sed -n "1 P" 
```

D'abord, pourquoi faire simple quand on peut faire compliqué...

```
ls /usr/bin | head -n 1
```

et ensuite, la différence entre P et p pour sed ne se vera que lorsque tu auras des '\n' dans ton 'pattern space', en gros, c'est soit quand tu le rajoutes à la main avec un s///, soit quand tu joues avec N, mais dans tous les cas, c'est hors de propos ici...

Si jamais tu tenais à le faire avec sed, alors, une manière artistique de le faire (oui! sed c'est tout un art  :Wink:  ) serait:

```
ls /usr/bin | sed 'q'
```

 Et si tu enlèves les simples quotes, ça fait encore plus obscure!

 :Laughing: 

----------

## Magic Banana

Bon... Visiblement j'étais hors-sujet en m'intéressant à la date de chacun des fichiers. Mais quand même. Lorsque tu as un petit fichier qui change au fin fond d'une hiérarchie, tu sauvegardes toute la hiérarchie de nouveau ? C'est quand même lourd tout ça, non ?

Sinon je ne crois toujours pas avoir compris où se situait le problème. Si c'est pour récupérer la date d'un fichier (qui peut-être un répertoire) et la comparer avec une autre date, je le fais dans ma fonction toBackup sans utiliser awk, sed ou même le moindre pipe. Juste des manipulation de chaîne de caractères en Shell. Question performance je pense donc que c'est meilleur.

----------

## kernelsensei

C'est pas un peu bourrin de recopier tous les fichiers à chaque fois ? Si tu peux te passer des archives, rsync + hardlinks c'est top. En plus tu peux rsync tranquilou par ssh, etc.

Cela dit je ne connais pas tes besoins.

----------

## loopx

 *XavierMiller wrote:*   

> find, avec l'option "-newer" donne tous les fichiers plus récents qu'un fichier donné (ton dernier tar de backup en l'occurence, ou un fichier timestamp daté de quelques minutes avant le tar)
> 
> et tar a une option "upgrade", qui n'ajoute que les nouveaux fichiers. Vu que tar EST le logiciel d'archivage sur cassette, autant l'utiliser simplement 

 

Ok pour les upgrade ... mais j'utilise du gzip dedans :s jpense qu'il voudra pas upgrader avec un gzip ...

----------

## loopx

 *kwenspc wrote:*   

> oui et avec tar tu peux aussi exclure certains rep/fichiers très facilement. Du coup pas besoin de faire une archive de chaque rep mais directement de l'ensemble (sans les rep exclus). Donc tu vires ta boucle for et zou.

 

Très juste ... mais imagine que sur certaine machine qui me sont inconnue, la racine soit pleine de crasse ? Bah, jvais toutes les ramassers si j'utilise un exclude ...

----------

## loopx

 *truc wrote:*   

> 
> 
> ```
> ls /usr/bin | sed -n "1 P" 
> ```
> ...

 

Waw  :Surprised: 

Tout d'abord, merci de m'avoir donné le nom du frère de "tail"  :Smile:     Ensuite, pour sed, c'est vraiment tordu la  :Surprised:    le 'q' est vraiment pas mal, je sais pu quoi utiliser  :Very Happy: 

Mais vu que "sed" est très puissant, jpense que jvais try avec "sed"  :Smile: 

Hiihihih, merci :p

EDIT:

Voilà ou j'en suis : 

```

serveur script # cat backup-system.sh                                                                                                       

#! /bin/sh                                                                                                                                  

# by loopx                                                                                                                                  

# 20081210                                                                                                                                  

##########                                                                                                                                  

DATE=`date '+%Y%m%d'`

BACKUP_DIR="/mnt/data2/backup/system"

let INTERVAL=1*60*60*24*7       #one week

let DATE_TEST=`date +%s`-$INTERVAL      #date used to test age of archives

TMP="/tmp"                                                                

backup() {

        #one instance max of this function

        if [ ! -f /tmp/system.backup ]    

        then                              

                date > /tmp/system.backup 

        else                              

                echo "> a backup is already running! (/tmp/system.backup)"

                return                                                    

        fi

        cd $BACKUP_DIR

        for DIR in bin boot etc home lib opt root sbin usr var

        do

                #select most recent archive of a gived directory

                lastBackupFile=`ls -t $BACKUP_DIR/*-$DIR-*.tar.gz | sed 'q'`

                #check old arhive; do backup if most recent archive is not valid or is too old

                if [[ ! -f $lastBackupFile || $DATE_TEST -gt `stat -c %Y $lastBackupFile` ]]

                then

                        echo "> doing backup of $DIR"

                        #backup to an other disk

                        tar cfz $BACKUP_DIR/system-$DIR-$DATE.tar.gz /$DIR

                        #cd because md5sum write the path gived (absolute) to the md5 file ...

                        md5sum system-$DIR-$DATE.tar.gz > system-$DIR-$DATE.md5

                fi

        done

        for DIR in bin boot etc home lib opt root sbin usr var

        do

                echo "> upload of $DIR"

                lastArchive=`ls -t $BACKUP_DIR/*-$DIR-*.tar.gz | sed 'q'`       #get the last archive

                lastArchiveMD5=`ls -t $BACKUP_DIR/*-$DIR-*.md5 | sed 'q'`       #and its MD5

                lftp -u backups,baba sftp://loop -e "cd /mnt/data/backup/system/serveur; put $lastArchive; $lastArchiveMD5; bye"

        done

        #remove backup older than 2 weeks

        find $BACKUP_DIR/ -type f -mtime 15 -exec rm {} \;

        rm /tmp/system.backup

}

if [ "$1" == "--backup" ]

then

        backup

fi

```

Le script peut crée donc un MD5, il peut supprimer les arvhives de plus de 14 jours (1 backup par semaine) et envoie aussi automatiquement les archives et md5 "récente" sur mon pc. Je sais pas si vous connaissiez "lftp" mais franchement, c'est de la bombe. Déjà, il connait les ftp de base, il connait ftpes et aussi sftp  :Surprised:    que dire de plus à par "merci lftp"  :Smile: .

Enfin bon, voilà, le script backup sur un autre disque local, puis backup via le réso ... Mais maintenant que jai un md5, il faudrait que je test ... or ... le test = l'exécution d'une commande sur une machine distante ... je ne sais pas trop quelle politique utiliser pour faire cela (ssh? plugin nagios NRE truc du genre? autre?).

Donc, mon serveur copie tout sur loop et il faut que le script sur serveur check que l'upload s'est bien déroulé et que le fichier n'est pas corrompu. Une idée ?

----------

## kwenspc

Toujours pas compris l'interet de faire n archives pour n rep à archiver  :Neutral: 

(tar te permet énormement de choses, autant en profiter)

----------

## loopx

 *kwenspc wrote:*   

> Toujours pas compris l'interet de faire n archives pour n rep à archiver 
> 
> (tar te permet énormement de choses, autant en profiter)

 

L'intéret ?

- un système automatique

- des pc sur lesquels les backups seront copié qui peuvent être up ou down à tout moment

- backup en wifi ... voir via le net ...

- mieux vaut envoyer 10x 1Go que 10Go d'un coup .. à la moindre coupure réso, je perd le fichier uploadé ...

Update de tar ne m'intéresse pas car je veux une nouvelles archive toute les semaines (avec un update, on ne peux pas revenir à la version d'il y a 2 semaines).

Voilà, tout est fait pour maximiser les chances de réussir un backup  :Wink: 

EDIT: comme je t'ai dis tantot, si à la racine, il y a mille rép ... et que j'ai exclu certain rep "courant" ... ben ok, ca ira mais j'aurais les backups de tout les autres répertoires qui se trouve dans / et que je ne connaissais pas  :Wink:      je pourrais faire un include ptet, mais ma technique me convient parfaitement car elle fait plusieurs fragments de la backup de mon système  :Wink: 

----------

## loopx

 *kernelsensei wrote:*   

> C'est pas un peu bourrin de recopier tous les fichiers à chaque fois ? Si tu peux te passer des archives, rsync + hardlinks c'est top. En plus tu peux rsync tranquilou par ssh, etc.
> 
> Cela dit je ne connais pas tes besoins.

 

J'ai pensé à rsync ... mais ... comment préserver les droits ??????

----------

## kwenspc

 *loopx wrote:*   

> 
> 
> - un système automatique
> 
> - des pc sur lesquels les backups seront copié qui peuvent être up ou down à tout moment
> ...

 

Euh ouais. C'est HS vu ma question là  :Wink:  (sinon oui j'ai bein compris l'interêt de ton script)

 *loopx wrote:*   

> 
> 
> - mieux vaut envoyer 10x 1Go que 10Go d'un coup .. à la moindre coupure réso, je perd le fichier uploadé ...
> 
> Bah une récup d'upload, le transfert reprend là où il s'était arreté.
> ...

 

 *loopx wrote:*   

> 
> 
> Update de tar ne m'intéresse pas car je veux une nouvelles archive toute les semaines (avec un update, on ne peux pas revenir à la version d'il y a 2 semaines).
> 
> 

 

Ah ouais nan mais perso aussi je serais resté à 1 tar pour une date.

 *loopx wrote:*   

> J'ai pensé à rsync ... mais ... comment préserver les droits ??????

 

Options 'a' et 'E'

----------

## loopx

Ouais, rsync, y avait moyen ... J'ai pensé à rsync ... du mauvais sens ... je l'ai vu uploadé les fichiers et que le user qui fait tourner rsyncd récupère les fichiers mais avec des droits uniquement pour lui donc, droit, masque était pu bon ...

Enfin, trop tard pour rsync, puis il ne compresse pas et envoye fichier par fichier sur le reso, pas top mais c'est vrai qu'il check avant si il faut les copier ou non.

Je vais garder les tar  :Wink: 

Sinon, j'aimerais savoir, est-ce chose courante d'ouvrir un ssh pour exécuter une commande sur un pc distant ?

genre :

```

loop serveur # cat *.md5

f18000009c56c88f7fb53203fbad3a54  system-bin-20081210.tar.gz

cae4517e1773d2bbe05458099feeeaad  system-boot-20081210.tar.gz

850231e7dab81d056f63547551645bf6  system-etc-20081210.tar.gz

dcf5f234ed5d4a78d467ea24f4f822ac  system-home-20081210.tar.gz

ee343703c592fa8a874e17f66ce7e463  system-lib-20081210.tar.gz

541072f2e2a7227c4c28766ea4982408  system-opt-20081210.tar.gz

b30ae894f75a9e23e6dea78c65a029fa  system-root-20081210.tar.gz

7f2c92c287809de1caeb55596cbb4ba5  system-sbin-20081210.tar.gz

loop serveur # md5sum -c *.md5

system-bin-20081210.tar.gz: OK

system-boot-20081210.tar.gz: OK

system-etc-20081210.tar.gz: OK

system-home-20081210.tar.gz: OK

system-lib-20081210.tar.gz: OK

system-opt-20081210.tar.gz: OK

system-root-20081210.tar.gz: OK

system-sbin-20081210.tar.gz: OK

```

Note que je devrais peut être car déjà, à la base, j'ai ouvert un port sshd pour uploader les archives ... donc à partir de ce moment la, jpeux aussi utiliser le ssh tout court, la sécu changer apas vraiment ... (niveau accès fichier du moins). Utiliser nagios et son plugin pour exécuter à distance, je trouve ca un peu lourd quand meme, ssh est plus présent que nagios sur les machines Unix/Linux.

----------

## xaviermiller

 *loopx wrote:*   

>  *XavierMiller wrote:*   find, avec l'option "-newer" donne tous les fichiers plus récents qu'un fichier donné (ton dernier tar de backup en l'occurence, ou un fichier timestamp daté de quelques minutes avant le tar)
> 
> et tar a une option "upgrade", qui n'ajoute que les nouveaux fichiers. Vu que tar EST le logiciel d'archivage sur cassette, autant l'utiliser simplement  
> 
> Ok pour les upgrade ... mais j'utilise du gzip dedans :s jpense qu'il voudra pas upgrader avec un gzip ...

 

"Je pense"... essaie au moins : l'informatique n'est pas un département "philo et lettres", mais une science  :Wink: 

----------

