Récupération d'articles d'archives
This commit is contained in:
@@ -0,0 +1,421 @@
|
||||
---
|
||||
comments_url: https://com.richard-dern.fr/post/526
|
||||
date: '2012-02-19 00:14:00'
|
||||
dossier:
|
||||
- Créer son propre Cloud
|
||||
links:
|
||||
- lang: fr
|
||||
name: Page d'origine sur Archive.org
|
||||
url: https://web.archive.org/web/20120221004524/http://ingnu.fr/2012/02/19/sauvegarder-et-restaurer-son-serveur/
|
||||
tags:
|
||||
- Backup
|
||||
- rsync
|
||||
- Sauvegarde
|
||||
title: Sauvegarder et restaurer son serveur
|
||||
weather:
|
||||
humidity: 96
|
||||
illuminance: 0.0
|
||||
precipitations: true
|
||||
pressure: 1012.4
|
||||
source:
|
||||
- open-meteo
|
||||
temperature: 3.6
|
||||
wind_direction: 226
|
||||
wind_speed: 16.5
|
||||
weight: 14
|
||||
---
|
||||
|
||||
Maintenant que nous disposons d'un serveur pratiquement complet pour [avoir son propre cloud](https://web.archive.org/web/20120221004524/http://ingnu.fr/category/creer-son-propre-cloud/), que nous avons [renforcé sa sécurité](https://web.archive.org/web/20120221004524/http://ingnu.fr/2012/02/13/renforcer-la-securite-de-son-serveur/) et que nous avons vu comment [opérer un monitoring basique](https://web.archive.org/web/20120221004524/http://ingnu.fr/2012/02/13/trucs-et-astuces-pour-son-serveur-prive/), nous allons voir comment sauvegarder et restaurer son serveur.
|
||||
|
||||
Nous allons faire appel au fameux [rsync](https://web.archive.org/web/20120221004524/http://rsync.samba.org/), pour ne pas encombrer notre serveur de solutions aussi lourdes à installer qu'à configurer, d'autant que je vous propose un script qui va simplifier tout ça, et même plus encore...
|
||||
|
||||
Vous pouvez placer ce script n'importe où : sur le serveur qui héberge vos services, sur votre propre machine, sur un serveur séparé, un NAS qui supporte rsync et l'authentification par clé, etc.
|
||||
Il suffit de configurer un peu le script pour que la sauvegarde se fasse presque toute seule.
|
||||
Elle est pas belle la vie Libre ?
|
||||
|
||||
## Choisir son dispositif de stockage
|
||||
|
||||
Communément, on sauvegarde sur une partition séparée, de préférence sur un disque séparé, peut être dans une machine séparée, ultimement dans un local séparé.
|
||||
Il n'y a véritablement que deux prérogatives à l'utilisation du script que je vous propose : la machine doit pouvoir utiliser rsync, et l'authentification par clé.
|
||||
Toute distribution GNU/Linux en est capable, vous ne devriez donc pas avoir trop de mal à disposer d'une plateforme adéquate.
|
||||
|
||||
Évidemment, une autre prérogative s'impose d'elle-même : l'espace disque disponible.
|
||||
|
||||
À titre d'exemple, sachez que j'utilise ce script pour sauvegarder deux serveurs et les documents d'une dizaine de personnes.
|
||||
Le premier, celui qui héberge ingnu.fr, héberge aussi tout un tas d'autres sites, un serveur mail d'une dizaine d'utilisateurs, les bases de données, etc.
|
||||
Au total, un snapshot des deux machines occupe à l'heure actuelle 7.6Go.
|
||||
|
||||
Mon script vous permet de disposer de deux types de sauvegardes : un instantané (appelé *snapshot*) et un instantané de chaque heure de chaque jour.
|
||||
Le premier instantané est en réalité vieux au maximum d'une minute, tandis que les autres instantanés vous permettent de remonter dans le temps par tranche d'une heure, sur un nombre de jours que vous pouvez déterminer.
|
||||
|
||||
Au final, sur cinq jours (qui est le réglage par défaut), l'espace disque total occupé par les sauvegardes n'est que doublé : il est actuellement de 13Go.
|
||||
Seuls les fichiers modifiés occupent la différence entre l'espace total et l'espace initial.
|
||||
|
||||
Vous n'avez donc pas besoin d'un disque de plusieurs téraoctets, à moins que vous ne vouliez sauvegarder aussi des fichiers comme des vidéos ou des distributions GNU/Linux en quantité industrielle...
|
||||
|
||||
## Créer la clé d'authentification
|
||||
|
||||
La communication entre le serveur et la machine qui exécute la sauvegarde (qui peut aussi être la même machine donc) se fait via rsync, donc ssh.
|
||||
La connexion est par conséquent chiffrée, et les transferts sont intelligents : la bande passante est minimisée.
|
||||
|
||||
Pour pouvoir tout sauvegarder d'un coup, on va donc sauvegarder en tant que root.
|
||||
Si vous sauvegardez depuis une machine distante, créez une clé avec la commande suivante :
|
||||
|
||||
```bash
|
||||
ssh-keygen -t rsa -f ~/.ssh/id_rsa_backup
|
||||
```
|
||||
|
||||
Que vous enverrez au serveur via la commande :
|
||||
|
||||
```bash
|
||||
ssh-copy-id -i ~/.ssh/id_rsa_backup.pub root@exemple.fr
|
||||
```
|
||||
|
||||
Vous devrez saisir le mot de passe root de la machine distante.
|
||||
Testez enfin l'accès :
|
||||
|
||||
```bash
|
||||
ssh root@exemple.fr
|
||||
```
|
||||
|
||||
Vous devriez être connecté sans avoir eu besoin de saisir votre mot de passe.
|
||||
|
||||
## Créer le script de sauvegarde
|
||||
|
||||
Créez un répertoire dédié au script et à sa configuration :
|
||||
|
||||
```bash
|
||||
mkdir -p /scripts/backup
|
||||
cd /scripts/backup
|
||||
mkdir conf.d include.d exclude.d
|
||||
```
|
||||
|
||||
Pour respecter le [Standard de Hiérarchie des Systèmes de Fichiers](https://web.archive.org/web/20120221004524/http://www.pathname.com/fhs/), nous devrions placer le script dans */usr/bin*, et la configuration dans */etc/backup*.
|
||||
Rien ne vous empêche de procéder de la sorte, à condition de modifier les chemins d'accès dans le script que nous allons voir tout de suite :
|
||||
|
||||
```bash
|
||||
nano backup
|
||||
```
|
||||
|
||||
```text
|
||||
#!/bin/bash
|
||||
|
||||
###############################################################################
|
||||
# Variables #
|
||||
###############################################################################
|
||||
|
||||
my_pid=$$
|
||||
my_dir=$(dirname $0)
|
||||
pid_file="/var/run/backup.pid"
|
||||
|
||||
conf_dir="$my_dir/conf.d"
|
||||
include_dir="$my_dir/include.d"
|
||||
exclude_dir="$my_dir/exclude.d"
|
||||
|
||||
log_dir="/var/log/backup"
|
||||
log_file="$log_dir/backup"
|
||||
|
||||
rsync_args="--archive --recursive --delete --delete-excluded"
|
||||
|
||||
backup_root="/mnt/backup"
|
||||
|
||||
rsync=$(which rsync)
|
||||
|
||||
current_date=$(date "+%Y-%m-%d")
|
||||
current_minute=$(date +%M)
|
||||
current_hour=$(date +%H)
|
||||
yesterday_date=$(date --date "yesterday" "+%Y-%m-%d")
|
||||
|
||||
max_age=5
|
||||
oldest_backup=$(date --date "$max_age days ago" "+%Y-%m-%d/%H")
|
||||
oldest_log=$(date --date "$max_age days ago" "+%Y-%m-%d")
|
||||
|
||||
###############################################################################
|
||||
# Fonctions #
|
||||
###############################################################################
|
||||
|
||||
function check_pid() {
|
||||
if [ -f "$pid_file" ]
|
||||
then
|
||||
old_pid=$(cat "$pid_file")
|
||||
old_pid_exists=$(ps -p $old_pid | grep -v TTY | awk -F " " '{print $1}')
|
||||
|
||||
if [ "$old_pid_exists" != "" ]
|
||||
then
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function log() {
|
||||
if [ "$2" == "true" -o "$2" == "TRUE" -o "$2" == "yes" -o "$2" == "YES" -o "$2" == "1" ]
|
||||
then
|
||||
log_date=$(date "+%d/%m/%Y %H:%M:%S")
|
||||
|
||||
echo "[$log_date] $1" >> "$log_file"
|
||||
else
|
||||
echo "$1" >> "$log_file"
|
||||
fi
|
||||
}
|
||||
|
||||
function check_dir() {
|
||||
if [ ! -d "$1" ]
|
||||
then
|
||||
mkdir -p "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Lancement de la procédure #
|
||||
###############################################################################
|
||||
|
||||
##### Vérification des journaux ###############################################
|
||||
|
||||
check_dir "$log_dir"
|
||||
|
||||
if [ ! -f "$log_file" ]
|
||||
then
|
||||
touch "$log_file"
|
||||
fi
|
||||
|
||||
##### Déplacement des anciens journaux ########################################
|
||||
|
||||
if [ "$current_hour" == "00" -a "$current_minute" == "00" ]
|
||||
then
|
||||
mv "$log_file" "$log_file-$yesterday_date"
|
||||
fi
|
||||
|
||||
##### Démarrage de la procédure ###############################################
|
||||
|
||||
check_pid
|
||||
|
||||
echo $my_pid > "$pid_file"
|
||||
|
||||
start_date=$(date "+%d/%m/%Y %H:%M:%S")
|
||||
|
||||
log " "
|
||||
log "###############################################################################"
|
||||
log "# Début de la procédure : $start_date #"
|
||||
log "###############################################################################"
|
||||
log " "
|
||||
|
||||
list=$(ls "$conf_dir")
|
||||
|
||||
for host in $list; do
|
||||
conf_file="$conf_dir/$host"
|
||||
|
||||
source "$conf_file"
|
||||
|
||||
host_rsync_args="$rsync_args"
|
||||
host_snapshot="$backup_root/$host/snapshot"
|
||||
|
||||
if [ "$ENABLED" != "yes" -a "$ENABLED" != "YES" -a "$ENABLED" != "true" -a "$ENABLED" != "TRUE" -a "$ENABLED" != "1" ]
|
||||
then
|
||||
log "**** L'hôte $host est désactivé ****"
|
||||
log " "
|
||||
continue
|
||||
fi
|
||||
|
||||
log "**** Traitement de l'hôte $host ****"
|
||||
log " "
|
||||
|
||||
source="$SOURCE"
|
||||
target="$host_snapshot"
|
||||
|
||||
check_dir "$target"
|
||||
|
||||
log "Source : $SOURCE" true
|
||||
log "Destination : $target" true
|
||||
|
||||
if [ -f "$include_dir/$host" ]
|
||||
then
|
||||
log "Un fichier d'inclusion existe : $include_dir/$host" true
|
||||
host_rsync_args="$host_rsync_args --files-from=$include_dir/$host"
|
||||
fi
|
||||
|
||||
if [ -f "$exclude_dir/$host" ]
|
||||
then
|
||||
log "Un fichier d'exclusion existe : $exclude_dir/$host" true
|
||||
host_rsync_args="$host_rsync_args --exclude-from=$exclude_dir/$host"
|
||||
fi
|
||||
|
||||
log "Commande : $rsync $host_rsync_args $source $target" true
|
||||
log "Démarrage de la création ou mise à jour de l'instantané..." true
|
||||
|
||||
$rsync $host_rsync_args $source $target
|
||||
|
||||
log "Création ou mise à jour de l'instantané terminée" true
|
||||
|
||||
##### Sauvegarde périodique ###############################################
|
||||
|
||||
if [ "$current_minute" == "00" ]
|
||||
then
|
||||
log " "
|
||||
log "Sauvegarde périodique" true
|
||||
|
||||
source="$host_snapshot/"
|
||||
target="$backup_root/$host/$current_date/$current_hour/"
|
||||
|
||||
check_dir "$target"
|
||||
|
||||
log "Source : $source" true
|
||||
log "Destination : $target" true
|
||||
log "Commande : $rsync $host_rsync_args --links-dest=$source $SOURCE $target" true
|
||||
log "Démarrage de la sauvegarde périodique..." true
|
||||
|
||||
$rsync $host_rsync_args --link-dest="$source" "$SOURCE" "$target"
|
||||
|
||||
log "Sauvegarde périodique terminée" true
|
||||
fi
|
||||
|
||||
##### Suppression des anciennes sauvegardes ###############################
|
||||
|
||||
log " "
|
||||
log "Recherche d'une ancienne sauvegarde ($backup_root/$host/$oldest_backup)..." true
|
||||
|
||||
if [ -d "$backup_root/$host/$oldest_backup" ]
|
||||
then
|
||||
log "Une ancienne sauvegarde existe : $backup_root/$host/$oldest_backup" true
|
||||
log "Suppression de la sauvegarde la plus ancienne..." true
|
||||
|
||||
rm -rf "$backup_root/$host/$oldest_backup"
|
||||
|
||||
log "Suppression terminée" true
|
||||
else
|
||||
log "Il n'existe pas d'ancienne sauvegarde" true
|
||||
fi
|
||||
|
||||
log " "
|
||||
done
|
||||
|
||||
end_date=$(date "+%d/%m/%Y %H:%M:%S")
|
||||
|
||||
log "###############################################################################"
|
||||
log "# Fin de la procédure : $end_date #"
|
||||
log "###############################################################################"
|
||||
log " "
|
||||
|
||||
rm -f "$pid_file"
|
||||
```
|
||||
|
||||
Important : Veuillez noter que ce script me convient bien : rien ne vous empêche de faire des ajustements pour qu'il vous corresponde à VOUS !
|
||||
|
||||
Notice : Modifiez impérativement la variable *backup_root* !
|
||||
|
||||
Quelques explications.
|
||||
Si vous voulez respecter les FHS, modifiez les variables *conf_dir*, *include_dir* et *exclude_dir*.
|
||||
Vous pouvez également modifier la variable *max_age*, dont la valeur (un entier) représente le nombre de jours à conserver.
|
||||
|
||||
Ensuite, quelques fonctions classiques : recherche d'un pid existant (pour ne pas lancer deux sauvegardes simultanées), journalisation, et recherche et création de répertoire.
|
||||
|
||||
La procédure commence alors par la vérification de l'existence des journaux et leur archivage.
|
||||
Puis, le script récupère la liste des fichiers contenus dans *conf.d*, lit chacun d'entre eux pour obtenir deux directives de configuration (*$ENABLED* true/false et *$SOURCE* représentant la source à sauvegarder), recherche s'il existe un fichier d'inclusion (il vaut mieux sinon vous sauvegardez toute la partition, se trouve dans le répertoire *include.d*) et un fichier d'exclusion (facultatif, se trouve dans *exclude.d*).
|
||||
|
||||
Chaque minute (via une tâche cron), le script se lance, et créé ou met à jour l'instantané (le contenu du répertoire *$backup_root/$host/snapshot*).
|
||||
Chaque heure, ce snapshot est créé dans un répertoire distinct, en faisant appel aux hard links : le fichier n'est pas copié, mais un hard link est créé.
|
||||
Autrement dit, le fichier est accessible depuis deux adresses différentes.
|
||||
Même si la source (dans le *snapshot*) est supprimée, le fichier existe toujours grâce au hard link.
|
||||
Dans notre cas, cela nous permet d'économiser de l'espace disque.
|
||||
|
||||
La conséquence de cette façon de procéder est de disposer à tout instant d'une image complète du système de fichiers sauvegardé.
|
||||
Et le but, c'est de le restaurer en une ligne de commande (une simple copie suffira).
|
||||
|
||||
Enfin, on supprime les instantanés les plus anciens.
|
||||
|
||||
Attribuez le droit d'exécution au script :
|
||||
|
||||
```bash
|
||||
chmod +x backup
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Vous disposez donc d'un répertoire *conf.d, include.d* et *exclude.d*.
|
||||
Le premier contiendra un fichier par machine à sauvegarder.
|
||||
Vous pouvez nommer ce fichier comme bon vous semble.
|
||||
Une seule règle à respecter : ce nom devra être le même que celui du fichier d'inclusions et du fichier d'exclusions.
|
||||
|
||||
Créons la configuration de notre cloud :
|
||||
|
||||
```bash
|
||||
nano conf.d/my_cloud
|
||||
```
|
||||
|
||||
```text
|
||||
ENABLED=true
|
||||
SOURCE=/
|
||||
```
|
||||
|
||||
Si le serveur est une machine différente, on utilisera la notation suivante :
|
||||
|
||||
```text
|
||||
SOURCE="root@exemple.fr:/"
|
||||
```
|
||||
|
||||
Avec cette configuration, on va sauvegarder l'ensemble de la machine concernée (ou plus exactement, l'intégralité de la partition */*).
|
||||
Ce n'est probablement pas ce que vous voulez, alors nous devons créer un fichier d'inclusions :
|
||||
|
||||
```bash
|
||||
nano include.d/my_cloud
|
||||
```
|
||||
|
||||
À peu de chose près, vous devriez mettre ceci :
|
||||
|
||||
```text
|
||||
/etc/amavis
|
||||
/etc/apache2
|
||||
/etc/bind
|
||||
/etc/clamav
|
||||
/etc/dovecot
|
||||
/etc/php5
|
||||
/etc/postfix
|
||||
/etc/prosody
|
||||
/etc/rc.local
|
||||
/etc/spamassassin
|
||||
/etc/ssl
|
||||
/opt
|
||||
/scripts
|
||||
/var/vmail
|
||||
/var/www
|
||||
/var/lib/mysql
|
||||
```
|
||||
|
||||
Avec ce contenu, vous devriez sauvegarder l'intégralité du serveur que nous avons configuré jusqu'à maintenant.
|
||||
|
||||
Pour éviter de sauvegarder des choses inutiles, créons un fichier d'exclusions :
|
||||
|
||||
```bash
|
||||
nano exclude.d/my_cloud
|
||||
```
|
||||
|
||||
```text
|
||||
log
|
||||
```
|
||||
|
||||
## Lancement
|
||||
|
||||
On édite la crontab de l'utilisateur qui procède à la sauvegarde :
|
||||
|
||||
```bash
|
||||
crontab -e
|
||||
```
|
||||
|
||||
```text
|
||||
* * * * * /scripts/backup/backup
|
||||
```
|
||||
|
||||
Et on vérifie le contenu du journal :
|
||||
|
||||
```bash
|
||||
tail -f /var/log/backup/backup
|
||||
```
|
||||
|
||||
## Restauration
|
||||
|
||||
Pour restaurer votre serveur, il suffit de copier vers lui tout ou partie de la dernière sauvegarde valide, via *scp*, tout simplement.
|
||||
Inutile de tergiverser : grâce à ce système de sauvegarde, il suffit d'une simple copie sécurisée pour restaurer le dernier état valide du serveur; contrairement à d'autres solutions de sauvegarde, pas besoin d'installer un agent sur la machine distante, une simple connexion ssh suffit !
|
||||
|
||||
## Conclusion
|
||||
|
||||
Nous voici arrivés à la fin de la série d'articles sur la création de son cloud personnel.
|
||||
Plus qu'un article à publier d'ici quelques minutes, alors à tout de suite !
|
||||
Reference in New Issue
Block a user