Recentemente ho scoperto il potere occulto di rsync!

Che la bash (o console) sia un luogo magico, terra fertile per il proliferare di nerd, geek e folletti… beh è cosa risaputa (con mastercard).

Che esse-esse-acc-arsi * su di un server remoto per salvare files importantissimi sia una emozione unica… beh anche questo è cosa risaputa (con mastercard).

Ma controllare che ogni giorno, ogni ora, il proprio script si occupi in maniera veloce e leggera di fare i backup… non ha prezzo!

(*) ovvero aprire una shell sicura ** su di una macchina remota con ssh

(**) no, non è una pratica sessuale

Ok, veniamo al succo: due server. Uno principale su cui gli utenti salvano i loro files (magari attraverso samba) ed uno secondario, di backup, che è il clone del primo. Lo scopo è semplice, se il primo server salta, il secondo lo può sostituire all’istante. In più sul secondo server si possono eseguire operazioni di backup o altro, senza occupare risorse del primo, che così rimane tutto a disposizione degli utenti.

Per fare questo abbiamo bisogno di 4 cose:

  1. uno script che sicronizzi i due server (rsync)
  2. una sessione autenticata in ssh che permetta la sincronizzazione in maniera automatica
  3. l’esecuzione automatica ad un orario prestabilito dello script
  4. uno script che faccia i backup (anch’esso ad orari prestabiliti)

Cominciamo dal primo server (quello principale) che chiameremo server1.

Punto 1: Rsync

Il comando rsync è molto utile poichè permette la sincronizzazione di due directory tramite il confronto dei files e la copia esclusivamente dei cambiamenti tra le due cartelle. In pratica è come eseguire un scp (secure copy) tra due cartelle, ma con un notevole risparmio di banda dato che solo le modifiche vengono trasmesse (trasferimento incrementale).

rsync --delete -azv -e ssh [dir1] [dir2]

Dove naturalmente [dir1] e [dir2] sono le due cartelle da tenere “clonate”, con “–delete” vengono anche eliminati i files che sono stati cancellati dalla [dir1] e con “ssh” gli diciamo di utilizzare una sessione in ssh… appunto.

Per specificare che la [dir2] è remota si usa la sintassi:

utente@macchina:cartella

Bene, vediamo adesso lo script nel suo insieme:

#!/bin/sh

#Author: fry@nerdsopolis.net
#Description: Backup tramite rsync.

#Variabili
LOCAL=/srv/samba/pub
REMOTE=/srv/samba/backup
HOST=192.168.1.100
LOG=/srv/samba/backup.log
SYNCLOG=/srv/samba/backup.synclog

#Inizio log
echo $(date +"%d/%m/%Y") | cat >> $LOG
echo $(date +"%H:%M.%S") backup started... | cat >> $LOG

#Rsync
rsync --delete -azv -e ssh $LOCAL root@$HOST:$REMOTE | cat > $SYNCLOG

#Fine log
echo $(date +"%H:%M.%S") backup ended! | cat >> $LOG

Come si può vedere non ho fatto altro che specificare un po’ di variabili ed aggiungere un file di log che ci permette di fare del debug sull’esecuzione di rsync.

La cartella locale è /srv/samba/pub e quella remota è /srv/samba/backup sul server2 che ha indirizzo 192.168.1.100.

NB: lo script utilizza l’utente root su entrambi i server. Naturalmente tale opzione è sconsigliabile ma per il momento semplifica le cose!

Mettiamo lo script (che io ho chiamato semplicemente rsync_backup.sh) nella cartella

/usr/local/bin

su server1 e rendiamolo avviabile

chmod u+x /usr/local/bin/rsync_backup.sh

Ora se proviamo ad avviarlo

sh /usr/local/bin/rsync_backup.sh

ci verrà richiesta la password dell’utente root sul server2 (ed anche si accettare la chiave se è la prima volta che ci connettiamo in ssh a quella macchina).

Poichè però il nostro script dovrà essere eseguito automaticamente, non possiamo inserire a mano la password tutte le volte. E, prima che a qualcuno venga in mente, non vogliamo neanche far passare password in chiaro tutte le volte!

Punto 2: SSH senza password

Per automatizzare l’operazione di ssh tra il server1 ed il server2 dobbiamo fare in modo che il server2 si “fidi ciecamente” del server1 senza bisogno di una password. Come? Utilizzando una combinazione di chiavi pubbliche e private.

Senza scendere nel dettaglio mi limiterò a ricordarvi (dato che voi già lo sapete) che posso distribuire liberamente la mia chiave pubblica e tenere al sicuro la mia chiave privata. Grazie alla chiave pubblica chiunque potrà essere sicuro della mia identità fin tanto che deterrò la chiave privata.

Sul server1 generiamo la coppia di chiavi

ssh-keygen -t rsa

lasciando generare le chiavi nella directory predefinita e non inserendo nessuna password quando ci viene chiesto.

Ora andiamo nella cartella .ssh/ nella home del nostro utente, troveremo due files: id_rsa e id_rsa.pub.

Ovvero: id_rsa = chiave privata & id_rsa.pub = chiave pubblica

Inviamo la nostra chiave pubblica al server2

scp id_rsa.pub root@192.168.1.100:/root

ora andiamo sul server2 nella cartella /root dove troviamo il file che abbiamo appena copiato. Adesso controlliamo di avere una cartella che si chiama “.ssh”, se non c’è creiamola. Poi mettiamo la chiave pubblica nel file “autorized_keys” all’interno della directory.

mv id_rsa.pub .ssh/
cat id_rsa.pub >> authorized_keys
chmod 644 authorized_keys

Ok! Adesso qualsiasi accesso in ssh dal server1 al server2 avverrà senza richiesta di password e quindi se proviamo a lanciare nuovamente il nostro script dal server1, la sincronizzazione avverrà senza richiesta di input.

NB. Come detto prima, eseguire queste operazioni con l’utente root è altissimamente sconsigliato!

Punto 3: Crontab

Crontab gestisce tutte le operazioni pianificate sul nostro server. L’utilizzo è semplicissimo:

0 4 * * * /usr/local/bin/rsync_backup.sh

esegue il nostro script alle 4:00 di tutti i giorni.

Per maggiori dettagli su crontab vi rimando a wikipedia.

La stringa che abbiamo visto sopra andrà inserita all’interno della coda di crontab, tramite il comando

crontab -e

si aprirà un editor (se è la prima volta ci chiede anche che editor usare, io consiglio vim) dove scrivere la stringa (in vim per modificare si preme “i”) e dopo averla salvata (premere “:x”) possiamo controllare che sia stata inserita tramite

crontab -l

Punto 4: Backup

Mentre il nostro server1 si becca tutti gli accessi degli utenti, il server2 rimane dormiente tutto il giorno e viene utilizzato solo per qualche minuto verso le 4 di notte, quando riceve gli aggiornamenti.

Possiamo quindi pianificare su server2 in qualsiasi altro momento della giornata dei backup (totali o incrementali) da masterizzare o da copiare su altri dischi.

Ecco lo script che uso io (backup totali tramite tar)

#!/bin/sh

#Author: fry@nerdsopolis.net
#Description: Script per la creazione di backup automatico e rimozione
#             vecchi backup.

#Variabili
LOG=/srv/samba/backup.log
TARLOG=/srv/samba/backup.tarlog
BASE=/srv/samba/backup/
DIR=pub/

#Inizio log
echo $(date +"%d/%m/%Y") | cat >> $LOG
echo $(date +"%H:%M.%S") backup started... | cat >> $LOG

#Creazione del backup
cd $BASE
tar -zcvf $(date +"%y%m%d-%H%M").tar $DIR | cat > $TARLOG

#Eliminazione backup piu' vecchio
first=$(ls | grep tar | sort -n | head -1)
rm $first
echo $(date +"%H:%M.%S") deleted $first | cat >> $LOG

#Fine log
echo $(date +"%H:%M.%S") backup ended! | cat >> $LOG

In questo caso il mio script crea un archivio tar compresso di tutta la cartella /srv/samba/backup/pub e successivamente cancella il backup più vecchio.

Naturalmente questa tecnica ci consente di tenere in memoria (a seconda dello spazio sul disco) tanti backup che sono la “foto” della cartella in un determinato momento. Se ad esempio tengo 10 backup, lo script andrà a crearne uno nuovo e poi a cancellare il più vecchio, lasciandone sempre 10 sul mio disco. Per fare ciò però dovremo ricordarci di fargli fare prima 10 backup commentando per i primi 10 cicli la riga relativa alla cancellazione dei backup più vecchi.

Anche questo script, come il precendete va messo in /usr/local/bin e chmoddato in modo da essere eseguibile.

Ora sempre tramite crontab possiamo fare in modo che lo script sia eseguito una volta alla settimana, la domenica notte:

0 4 * * 0 /usr/local/bin/backup.sh

Fine. Se avete avuto la forza di seguire questo post fino a questa riga, significa che avete realemente bisogno di usare gli script per fare i backup.

Quindi perchè non andate oltre e li personalizzate per fare altre funzioni? Si sa, uno script tira l’altro!

>