Raspberry PI Backup incrementale
Come creare un sistema di backup incrementale tramite Raspberry PI
1. La storia
In passato ho sempre creato periodicamente il Backup incrementale dei dati maggiormente utilizzati e allo scopo ho utilizzato il sempre validissimo e completo Cobian Backup che sebbene non sia più supportato esegue in modo assolutamente egregio e direi professionale il suo compito.
Era pero' necessario mantenere il PC acceso in quanto sebbene in Background Cobian Backup ha bisogno di una macchina windows per girare.
Recentemente ho rivisto la mia rete di casa creando mediante il nuovo FritzBox 3490 e un disco USB (Samsung D3 4TB) un NAS sempre disponibile da qualsiasi periferica connessa alla rete e anche in remoto tramite VPN. Il NAS che avevo un Synology 108j da 1TB è infatti diventato obsoleto per supportare tutto il carico domestico e rimane dedicato a fare da server multimediale.
Si riporta nel seguito il sistema implementato con la precisazione che nella definizione del sistema si è preso spunto adattandolo alle esigenze personali di quanto riportato da Grabriele Merli in merito, articolo di sicuro aiuto per capire, analizzare e impostare un buon sistema di backup incrementale.
2. Sorgente - destinazione - nomi dei file di backup
Il file di backup sarà del tipo:
- mntPnt/dstDsk/dstDir/souDsk/_souDir_fff_iii_AAAAMMGG_hhmmss.tar.gz
- /mnt/LCIE_Y/ZBK/M4TB_Q/_App_001_005_20170530_201001.tar.gz
Dove:
- mntPnt --> punto di mount dei dischi;
- dstDsk --> nome del disco destinazione;
- dstDir --> nome della cartella all'interno della quale creare il backup;
- souDsk --> nome del disco sorgente;
- souDir --> nome della cartella di cui si creerà il backup;
- fff --> indice del numero del backup completo (full);
- iii --> indice del numero del backup incrementale;
- AAAAMMGG --> data del backup Anno Mese Giorno;
- hhmmss --> ora del backup ora minuti secondi;
- .tar.gz --> estenzione del backup in formato tar compresso con gzip (GNU zip);
3. Montaggio sorgente destinazione:
- verifica della presenza di un file nella directory sorgente
- montaggio del disco corrispondente
- sudo mount......
- verifica della presenza di un file nella directory destinazione
- montaggio del disco corrispondente
- sudo mount......
Codice sorgente
#
# controllo mount disco sorgente --> verica presenza della cartella
#
while true; do
if [ -d ${souFil} ]
then
echo "Mount disco ${souFil} --> Ok" >> ${logFil}
echo $linea >> ${logFil}
break
else
echo "Mount disco ${souFil} --> No Ok" >> ${logFil}
echo $linea >> ${logFil}
#
sudo mount -t cifs -o user=Utente,pass=Password //192.168.188.1/Zappoco/Seagate-D3Station-01/_DiscoW ${mntPnt}${souDsk}
sleep 30s
fi
done
#
# controllo mount disco destinazione --> verica presenza della cartella
#
while true; do
if [ -d ${dstFil} ]
then
echo "Mount disco ${dstFil} --> Ok" >> ${logFil}
echo $linea >> ${logFil}
break
else
echo "Mount disco ${dstFil} --> No Ok" >> ${logFil}
echo $linea >> ${logFil}
#
sudo mount -t cifs -o user=Utente,pass=Password //192.168.188.1/Zappoco/ /mnt/LCIE_Y
echo "ho montato ${mntPnt}${dstDsk}"
sleep 30s
fi
done
4. Ricerca dell'ultimo backup:
- esecuzione di un ciclo di for
- determinazione del numero di backup full {ultF}
- determinazione del numero di backup incrementale {ultI}
Codice sorgente
#
# cerca la prima e ultima versione Full
#
for (( inF = 0 ; inF < ${maxT} ; inF++))
do
NinF=$( printf "%03d" ${inF} )
tarTmp="${dstFil}/${souDsk}/${tarFil}_${NinF}*"
cmdTmp="ls -1 ${tarTmp} 2> /dev/null | wc -l"
nTmp=`eval $cmdTmp`
if [ ! ${nTmp} -eq 0 ]
then
if [ ${prmF} -eq -1 ]
then
prmF=${inF}
ultI=${nTmp}
else [ ${ultF} -gt 0 ]
ultF=${inF}
ultI=${nTmp}
fi
else
if [ ${ultF} -gt 0 ]
then
break
fi
fi
done
if [ ${prmF} -eq -1 ]
then
prmF=0
ultI=0
fi
if [ ${ultF} -eq -1 ]
then
ultF=${prmF}
fi
echo "prmF = ${prmF}"
echo "ultF = ${ultF}"
echo "ultI = ${ultI}"
if [ ${ultI} -ge ${maxI} ]
then
ultI=0
ultF=$((${ultF}+1))
fi
tmpF=$(( ${ultF} - ${maxF} - 1 ))
echo "prmF = ${prmF}"
echo "tmpF = ${tmpF}"
if [ ${prmF} -eq ${tmpF} ]
then
NinF=$( printf "%03d" ${prmF} )
tarTmp="${dstFil}/${souDsk}/${tarFil}_${NinF}*"
echo $linea "Cancellazione ${tarTmp}" >> ${logFil}
echo $linea >> ${logFil}
echo "prmF = ${prmF}"
#
# rimuove i file 000
#
rm -f ${tarTmp} >> ${logFil}
fi
#
echo "ultF = ${ultF}"
echo "ultI = ${ultI}"
echo "Indice del backup completo --> ${ultF}" >> ${logFil}
echo "Indice del backup incrementale --> ${ultI}" >> ${logFil}
echo $linea >> ${logFil}
#
if [ ${ultI} -eq 0 ]
then
echo "Cancellazione ${snaFil}" >> ${logFil}
echo $linea >> ${logFil}
rm -f ${snaFil} >> ${logFil}
echo "Conversione del backup in completo" >> ${logFil}
else
echo "Creazione backup incrementale" >> ${logFil}
fi
echo $linea >> ${logFil}
5. Composizione del nome e del comando:
- composizione del nome
- composizione del comando
- esecuzione comando
Codice sorgente
NinF=$( printf "%03d" ${ultF} )
NinI=$( printf "%03d" ${ultI} )
#
tarTmp="${dstFil}/${souDsk}/${tarFil}_${NinF}_${NinI}_${dateSt}"
echo "Backup --> ${tarTmp}" >> ${logFil}
echo $linea >> ${logFil}
#
# esegue il comando tar
#
tar --listed-incremental=${snaFil} --no-check-device -zcvf ${tarTmp}.tar.gz ${souFil} ${excCm1} ${excCm2} ${excCm3} ${excCm4} >> ${logFil}
cp ${snaFil} "${dstFil}/${souDsk}/${tarFil}S${NinF}_${NinI}_${dateSt}.snar"
6. Codice completo
#! /bin/bash
#
# 2017 05 01 ZappocoS --> versione 001 --> partendo da schema RSYNC
# 2017 05 05 ZappocoS --> versione 003 --> inserimento funzione
#
#
#Per ripristinare
#
#Prima il full
#
#tar --listed-incremental=/dev/null -xzvf DirBak_000_000_20170505_180537.tar.gz
#
#Poi i vari incrementali dal più vecchio al più nuovo (e ti fermi dove vuoi arrivare)
#
#tar --listed-incremental=/dev/null -xzvf DirBak_000_001_20170506_190537.tar.gz
#tar --listed-incremental=/dev/null -xzvf DirBak_000_002_20170506_200537.tar.gz
#tar --listed-incremental=/dev/null -xzvf DirBak_000_003_20170507_210537.tar.gz
#SE SEI ROOT E VUOI RIPRISTINARE ANCHE I PERMESSI METTICI UN -p
#
#--------------------------
function tar_directory ()
{
linea="----------"
#linea=""
souDsk=$1 #disco di mount sorgente
souDir=$2 #cartella di cui creare TAR
dstDsk=$3 #disco di mount destinazione
dstDir=$4 #cartella dove creare TAR
mntPnt="/mnt/" #punto di mount
logPnt="/home/pi/Z_LOG/" #posizione file log
dateSt=`date +%Y%m%d_%H%M%S` #rappresentazione completa della data
souFil="${mntPnt}${souDsk}/${souDir}" #Nome completo della directory sorgente
dstFil="${mntPnt}${dstDsk}/${dstDir}" #Nome completo della directory destinazione
tarFil="${souDir}"
if [[ -z "$5" ]] ; then
excCm1=""
else
excCm1="--exclude ${souFil}/$5" #directory da escludere
fi
if [[ -z "$6" ]] ; then
excCm2=""
else
excCm2="--exclude ${souFil}/$6" #directory da escludere
fi
if [[ -z "$7" ]] ; then
excCm3=""
else
excCm3="--exclude ${souFil}/$7" #directory da escludere
fi
if [[ -z "$8" ]] ; then
excCm4=""
else
excCm4="--exclude ${souFil}/$8" #directory da escludere
fi
snaFil="${dstFil}/${souDsk}/${tarFil}.snar" #Nome del file contenente gli elenchi (listed-incremental)
logFil="${logPnt}${dateSt}_ZBK_${souDsk}__${tarFil}.log" #Nome completo del file di log
echo $linea
echo "Creazione del backup (zbk) by Zappoco 1.03"
echo "Data --> ${dateSt}"
echo $linea
echo "souFil = $souFil"
echo "dstFil = $dstFil"
echo "tarFil = $tarFil"
echo "dstPnt = $dstPnt"
echo "dstDir = $dstDir"
echo "logPnt = $logPnt"
echo "dateSt = $dateSt"
echo "snaFil = $snaFil"
echo "logFil = $logFil"
echo "excCm1 = $excCm1"
echo "excCm2 = $excCm2"
echo "excCm3 = $excCm3"
echo "excCm4 = $excCm4"
echo $linea
#
# inizializzazione dei parametri per il backup completo e incrementale
#
maxT=100 # numero massimo di backup ---> inserire 999
maxF=6 # numero massimo di back Full da mantenere
maxI=26 # numero massimo di back Incrementali per ogni Full
prmF=-1 # primo back full
ultF=-1 # ultimo back full
echo $linea >> ${logFil}
echo "Creazione del backup (zbk) by Zappoco 1.03" >> ${logFil}
echo "Data --> ${dateSt}" >> ${logFil}
echo $linea >> ${logFil}
echo "Sorgente --> ${souFil}" >> ${logFil}
echo "Destinazione --> ${dstFil}" >> ${logFil}
echo " --> ${excCm1}" >> ${logFil}
echo " --> ${excCm2}" >> ${logFil}
echo " --> ${excCm3}" >> ${logFil}
echo " --> ${excCm4}" >> ${logFil}
echo "" >> ${logFil}
echo "Num. max di backup completi --> ${maxF}" >> ${logFil}
echo "Num. max di backup incrementali --> ${maxI}" >> ${logFil}
echo $linea >> ${logFil}
#
# controllo mount disco sorgente --> verica presenza della cartella
#
while true; do
if [ -d ${souFil} ]
then
echo "Mount disco ${souFil} --> Ok" >> ${logFil}
echo $linea >> ${logFil}
break
else
echo "Mount disco ${souFil} --> No Ok" >> ${logFil}
echo $linea >> ${logFil}
#
sudo mount -t cifs -o user=Utente,pass=Password //192.168.188.1/Zappoco/Seagate-D3Station-01/_DiscoW ${mntPnt}${souDsk}
sleep 30s
fi
done
#
# controllo mount disco destinazione --> verica presenza della cartella
#
while true; do
if [ -d ${dstFil} ]
then
echo "Mount disco ${dstFil} --> Ok" >> ${logFil}
echo $linea >> ${logFil}
break
else
echo "Mount disco ${dstFil} --> No Ok" >> ${logFil}
echo $linea >> ${logFil}
#
sudo mount -t cifs -o user=Utente,pass=Password //192.168.188.1/Zappoco/ /mnt/LCIE_Y
echo "ho montato ${mntPnt}${dstDsk}"
sleep 30s
fi
done
#
# cerca la prima e ultima versione Full
#
for (( inF = 0 ; inF < ${maxT} ; inF++))
do
NinF=$( printf "%03d" ${inF} )
#tarTmp="${dstPnt}${dstDsk}/${souDsk}/${tarFil}_${NinF}*"
tarTmp="${dstFil}/${souDsk}/${tarFil}_${NinF}*"
cmdTmp="ls -1 ${tarTmp} 2> /dev/null | wc -l"
nTmp=`eval $cmdTmp`
#echo "${nTmp} ${prmF} ${ultF} $tarTmp"
if [ ! ${nTmp} -eq 0 ]
then
if [ ${prmF} -eq -1 ]
then
prmF=${inF}
ultI=${nTmp}
#echo "primo full ${NinF} -SI- ${prmF}"
else [ ${ultF} -gt 0 ]
ultF=${inF}
ultI=${nTmp}
#echo "utimo full ${NinF} -SI- ${ultF}"
fi
else
if [ ${ultF} -gt 0 ]
then
#echo trovato ultimo
break
fi
fi
done
#
if [ ${prmF} -eq -1 ]
then
prmF=0
ultI=0
fi
#
if [ ${ultF} -eq -1 ]
then
ultF=${prmF}
fi
#
echo "prmF = ${prmF}"
echo "ultF = ${ultF}"
echo "ultI = ${ultI}"
#
if [ ${ultI} -ge ${maxI} ]
then
ultI=0
ultF=$((${ultF}+1))
fi
tmpF=$(( ${ultF} - ${maxF} - 1 ))
echo "prmF = ${prmF}"
echo "tmpF = ${tmpF}"
if [ ${prmF} -eq ${tmpF} ]
then
NinF=$( printf "%03d" ${prmF} )
#tarTmp="${dstPnt}${souDsk}/${souDsk}/${tarFil}_${NinF}*"
tarTmp="${dstFil}/${souDsk}/${tarFil}_${NinF}*"
echo $linea "Cancellazione ${tarTmp}" >> ${logFil}
echo $linea >> ${logFil}
echo "prmF = ${prmF}"
#
# rimuove i file 000
#
rm -f ${tarTmp} >> ${logFil}
fi
#
echo "ultF = ${ultF}"
echo "ultI = ${ultI}"
echo "Indice del backup completo --> ${ultF}" >> ${logFil}
echo "Indice del backup incrementale --> ${ultI}" >> ${logFil}
echo $linea >> ${logFil}
#
if [ ${ultI} -eq 0 ]
then
echo "Cancellazione ${snaFil}" >> ${logFil}
echo $linea >> ${logFil}
rm -f ${snaFil} >> ${logFil}
echo "Conversione del backup in completo" >> ${logFil}
else
echo "Creazione backup incrementale" >> ${logFil}
fi
echo $linea >> ${logFil}
#
NinF=$( printf "%03d" ${ultF} )
NinI=$( printf "%03d" ${ultI} )
#
tarTmp="${dstFil}/${souDsk}/${tarFil}_${NinF}_${NinI}_${dateSt}"
echo "Backup --> ${tarTmp}" >> ${logFil}
echo $linea >> ${logFil}
#
# esegue il comando tar
#
tar --listed-incremental=${snaFil} --no-check-device -zcvf ${tarTmp}.tar.gz ${souFil} ${excCm1} ${excCm2} ${excCm3} ${excCm4} >> ${logFil}
cp ${snaFil} "${dstFil}/${souDsk}/${tarFil}S${NinF}_${NinI}_${dateSt}.snar"
#if [ ${ultI} -eq 0 ]
#then
# echo "${NinF}_${NinI}" >> ${snaFil}
#fi
#echo "${NinF}_${NinI}" >> ${tarTmp}.txt
#
echo $linea >> ${logFil}
echo "Creazione del backup completata" >> ${logFil}
dateSt=`date +%Y%m%d_%H%M%S` #rappresentazione completa della data
echo "Data --> ${dateSt}" >> ${logFil}
echo $linea >> ${logFil}
#echo " ${logFil} ${dstFil} "
cp ${logFil} ${dstFil}
}
#
# souDsk souDir dstDsk dstDir excDi1 excDi2 excDi3 excDi4
#
tar_directory "M4TB_W" "Doc_ZappocoS" "LCIE_Y" "ZBK"
tar_directory "M4TB_W" "Doc_Nadia" "LCIE_Y" "ZBK"
tar_directory "M4TB_W" "Doc_ZappocoJ" "LCIE_Y" "ZBK"
tar_directory "M4TB_W" "Musica" "LCIE_Y" "ZBK"
tar_directory "M4TB_W" "Pdf" "LCIE_Y" "ZBK"
tar_directory "M4TB_W" "Sys" "LCIE_Y" "ZBK"
tar_directory "M4TB_W" "V_Foto" "LCIE_Y" "ZBK" 2016 2015 2014 2013
tar_directory "M4TB_W" "V_Video" "LCIE_Y" "ZBK"
tar_directory "M4TB_W" "Manuali_Libri_Ebook" "LCIE_Y" "ZBK" "Z_Libri_Liceo_CD"
#
echo
echo "ZBK processo completato"
echo
exit
ZappocoS, aprile maggio 2017