Repository 32bit  Forum
Repository 64bit  Wiki

Organizzare un backup completo

Da Slacky.eu.
Versione delle 18:00, 21 ott 2007, autore: Slacky (Discussione | contributi)

(diff) ← Versione meno recente | Versione attuale (diff) | Versione più recente → (diff)

Descrizione

Questo script ha lo scopo di organizzare un backup completo di un path liberamente definibile. Lo script organizza i dati in immagini iso di grandezza definibile e le masterizza man mano.

Download

http://www.slacky.eu/misto/concorso/tiferet/backntar

Script

#!/bin/bash
# The bash/sh interpreter
# ***************************************************************************************
# questo script ha lo scopo di organizzare un backup completo di
# un path liberamente definibile. Lo script organizza i dati in
# immagini iso di grandezza definibile e le masterizza man mano.
# ***************************************************************************************

# =======================================================================================
# inizio dichiarazione delle funzioni
# =======================================================================================

function dohelp ()
{
# se mi chiedi aiuto o non sai come usarmi, ti spiego

echo "$(basename $0) v2.0
Questo script ha lo scopo di organizzare un backup completo di
un path liberamente definibile. Lo script organizza i dati in
immagini iso di grandezza definibile e le masterizza man mano."

echo "Utilizzo:
$(basename $0) [opzioni] [specifiche]

OPZIONI:
-h, --help:	stampa questo help ed esce.
-c, --conf:	mostra la configurazione contenuta all'interno
		del file ~/$backfile, se esiste.
-f, --file:	effettua il backup con le impostazioni contenute
		all'interno del file ~/$backfile, se esiste.
-s, --save:	effettua il backup con le impostazioni che gli sono
		fornite di seguito
-r, --resume:	riprende l'ultimo backup effettuato.
--quiet:	quando è data questa opzione, le immagini ISO sono
		create senza soluzione di continuità.

SPECIFICHE:
Se è utilizzata la funzione -s, allora devono essere dati i seguenti dati
in quest'ordine:
$(basename $0)	-s backup={backdir} exclude={excdir} optdim={optdim}
		isodim={isodim} maxdim={maxdim}

backdir:	path completo della directory da organizzare per il backup
excdir:		nomi delle sotto-directory da escludere, separati da |
optdim:		dimensione ottimale delle cartelle da comprimere
isodim:		dimensione approssimativa finale dell'immagine ISO
maxdim:		dimensione massima del supporto utilizzato

ovviamente deve risultare optdim << isodim < maxdim

Se è utilizzata la funzione -s, allora devono essere forniti i seguenti dati:
$(basename $0)	-r {prev_path} {n}

prev_path:	percorso completo della directory creata durante l'ultimo backup
n:		indice dell'immagine ISO successiva all'ultime creata
"

exit 0
}

function doconf ()
{
# se mi chiedi la configurazione attuale, te la do senza discutere

# controllo se il file di configurazione esiste
preleva_conf

# stampo la configurazione
echo "*************************************************************************"
echo "Sarà effettuato il backup completo della directory $backdir"
echo "La dimensione dell'immagine ISO è impostata a $isodim MB"
echo "La dimensione ottimale è impostata a $optdim MB"
echo "La dimensione dei supporti è impostata a $maxdim MB"
echo "*************************************************************************"

exit 0
}

function preleva_conf ()
{
# la funzione preleva_conf serve per verificare, ove necessario, l'esistenza del
# file di configurazione e quindi di prelevare i valori corretti delle imnpostazioni
if [ ! -e ~/$backfile ]; then
	echo "Non esiste ancora un file di configurazione!"
	echo "Ne creerò uno di default, ma è opportuno controllarlo!"
	echo "backup_path	:{please, insert path for directory to backup}:" > ~/$backfile
	echo "iso_dimension	:4200:" >> ~/$backfile
	echo "opt_dimension	:1024:" >> ~/$backfile
	echo "max_dimension	:4400:" >> ~/$backfile
	echo "exclude_path	:foo1|foo2|foo3:" >> ~/$backfile
	exit 1
else
	backdir=$(grep 'backup' ~/$backfile | cut "-d:" -f2)
	isodim=$(grep 'iso' ~/$backfile | cut "-d:" -f2)
	optdim=$(grep 'opt' ~/$backfile | cut "-d:" -f2)
	maxdim=$(grep 'max' ~/$backfile | cut "-d:" -f2)
	excpath=$(grep 'exclude' ~/$backfile | cut "-d:" -f2)
	return 0
fi
}

function preleva_dati () # modificare in modo che l'utente debba inserire una sintassi del tipo variabile=valore
{
# la funzione preleva_dati serve per assegnare correttamente i parametri alle variabili
arg1=$(echo "$*" | egrep -o "backup=.*" | cut "-d=" -f2 | cut "-d " -f1)
arg2=$(echo "$*" | egrep -o "exclude=.*" | cut "-d=" -f2 | cut "-d " -f1)
arg3=$(echo "$*" | egrep -o "isodim=.*" | cut "-d=" -f2 | cut "-d " -f1)
arg4=$(echo "$*" | egrep -o "optdim=.*" | cut "-d=" -f2 | cut "-d " -f1)
arg5=$(echo "$*" | egrep -o "maxdim=.*" | cut "-d=" -f2 | cut "-d " -f1)

backdir=${arg1:-~}
excpath=${arg2:-""}
isodim=${arg3:-"4200"}
optdim=${arg4:-"1024"}
maxdim=${arg5:-"4400"}
}

function preleva_resume ()
{
# la funzione preleva_resume ha il compito di impostare correttamente i dati di backup
# relativi ad un backup precedentemente interrotto. Devono essere forniti:
# il percorso della directory temporanea del backup precedente e il numero progressivo
# del backup da eseguire
tempdir="$1"
n="$2"

# per evitare che siano ricreate le liste dei file e delle directory, imposto la
# variabile $work a "resume"
work="resume"

# prelevo i dati dell'ultimo backup
backdir=$(grep 'backup' $tempdir/$confile | cut "-d:" -f2)
isodim=$(grep 'iso' $tempdir/$confile | cut "-d:" -f2)
optdim=$(grep 'opt' $tempdir/$confile | cut "-d:" -f2)
maxdim=$(grep 'max' $tempdir/$confile | cut "-d:" -f2)
excpath=$(grep 'exclude' $tempdir/$confile | cut "-d:" -f2)
line=$(grep 'line' $tempdir/$confile | cut "-d:" -f2)
}

function se_corretta_sintassi ()
{
#  la funzione se_corretta_sintassi verifica che sia stato dato il corretto numero e
# formato di dati del backup.

# path inesistente?
if [ ! -e $backdir ]; then
	echo "Penso che tu abbia sbagliato ad indicarmi il percorso..."
	exit 1
# ordine sbagliato?
elif [ $optdim -gt $isodim ]; then
	echo "La dimensione ottimale ($optdim MB) non può essere superiore"
	echo "alla dimensione dell'immagine ISO ($isodim MB)."
	exit 1
elif [ $isodim -gt $maxdim ]; then
	echo "La dimensione dell'immagine ISO ($isodim MB) non può essere superiore"
	echo "alla dimensione del supporto ($maxdim MB)."
	exit 1
fi

# creo il file config contenente le informazioni sul backup, per un evantuale resume
if [ "$work" != "resume" ]; then
	echo "backup_path	:$backdir:
iso_dimension	:$isodim:
opt_dimension	:$optdim:
max_dimension	:$maxdim:
exclude_path	:$excpath:" > $tempdir/$confile
fi
}

function crea_lista ()
{
# la funzione crea_lista serve ad ottenere i file $okdir e $sparefile che contengono
# l'elenco delle directory aventi dimensioni inferiori a $optdim e l'elenco dei file
# rimanenti.

# controllo che la directory $backdir non entri in un singolo supporto; in quel caso non
# c'é bisogno di fare alcunché, altrimenti creo la lista delle sottodirectory, eliminando
# la prima riga che contiene proprio la $backdir
if [ "$totdim" -gt "$maxdim" ]; then
	du -k --max-depth 1 --exclude=.* $backdir | head -n -1  | sort -nr -o $kodir
else
	echo "La directory $backdir ha un dimensione inferiore a quella di un singolo"
	echo "supporto: $totdim KB < $maxdim KB. Pertanto non è necessario proseguire."
	exit 0
fi

# se la directory da backuppare non entra in un singolo supporto,
# allora è meglio scomporla in più sotto-directory.
while [ "`cat $kodir`" ]; do
	read line1 < $kodir
	dirdim=$(echo $line1 | cut "-d " -f1)
	dirname=$(echo $line1 | cut "-d " -f2-)
	if [ "$dirdim" -gt "$optdim" ]; then
		du -k --max-depth 1 "$dirname" | head -n -1 >> $kodir
		find "$dirname" -maxdepth 1 -type f -printf "%k\t%p\n" >> $sparefiles
		sed 1d $kodir | sort -nr -o $kodir
	else
		echo -e "$dirdim\t$dirname" >> $okdir
		sed 1d $kodir | sort -nr -o $kodir
	fi
done

#  elimino dai file $okdir e $sparefiles i path da escludere
if [ $excpath ]; then
	sed -r /$excpath/d $okdir | sort -nr -o $okdir
	sed -r /$excpath/d $sparefiles | sort -nr -o $sparefiles
fi

# creo una copia di backup delle due liste
cp $okdir $tempdir/backup_$(basename $okdir)~
cp $sparefiles $tempdir/backup_$(basename $sparefiles)~

# conto di quante linee siano composti i due elenchi e sommo i risultati. Il totale
# costituisce il numero massimo di iterazioni che si può compiere per creare una
# singola immagine ISO, quindi scrivo il risultato nel file $confile
local dirlines=$(wc -l $okdir | cut "-d " -f1)
local filelines=$(wc -l $sparefiles | cut "-d " -f1)
let "line=$dirlines+$filelines"
echo "line		:$line:" >> $tempdir/$confile

return
}

function se_entra ()
{
# la funzione se_entra ha il compito di verificare che il primo elemento dell'elenco
#  trasmessogli come argomento abbia dimensioni tali da entrare nella directory $isodir

# prendo la lista che mi viene passata
local list="$1"

# leggo la prima riga, ossia la directory (o file) più grande
if [ -s $list ]; then
	local line1
	read line1 < $list
else
	return 1
fi
dirdim=$(echo $line1 | cut "-d " -f1)

# verifico lo spazio disponibile e dunque se la directory (o file) può entrare
local busydim=$(du -k --max-depth 0 $isodir | cut -f1)
# let "busydim=1024*100*$i"
local freedim
let "freedim=$isodim-$busydim"
if (( $dirdim <= $freedim )); then
	return 0
else
	sed 1d $list > $filetemp
	mv -f $filetemp $list
	echo $line1 >> $list
	return 1
fi
}

function comprimi ()
{
# la funzione "comprimi" ha la funzione di comprimere in un archivio .tar.bz2 la directory
# contenuta nella prima riga della lista delle directory da backuppare. Tale lista deve
# essere passata come primo argomento.

# prendo la lista che mi viene passata
local list="$1"

# leggo la prima riga, ossia la directory (o file) più grande
local line1
read line1 < $list
local dirpath=$(echo $line1 | cut "-d " -f2-)

# creo il nome dell'archivio
archname="$(echo $dirpath | sed s:$backdir/::g | sed s:/:_:g | sed s:" ":_:g)"

# comprimo la directory più grande
echo -n " $(basename "$dirpath")..."
if se_compresso "$(basename "$dirpath")"; then
	tar -cvjf $isodir/$archname.tar.bz2 "$dirpath" >> $tempdir/tar_output 2>&1
# 	touch $isodir/$(basename $dirpath).tar.bz2
else
	tar -cvf $isodir/$archname.tar "$dirpath" >> $tempdir/tar_output 2>&1
# 	touch $isodir/$(basename $dirpath).tar
fi

# cancello la prima riga dalla lista
sed 1d $list > $filetemp
mv -f $filetemp $list

return 0
}

function se_compresso ()
{
# la funzione se_compresso verifica se l'argomento passato è già stato compresso e
# restituisce 1 o 0 a seconda che sia stato o no compresso.

local file="$1"

# con egrep verifico se nel nome del file sia contenuta un'estensione tipica dei
# formati compressi
local zip=$(echo $file | egrep .'\<tar\>|\<rar\>|\<zip\>|\<gz\>|\<bz2\>|\<tgz\>|\<iso\>')

# restituisco il valore opportuno
if [ "$zip" ]; then
	return 1
else
	return 0
fi

}

function se_pieno ()
{
# la funzione se_pieno verifica che la cartella $isodir non abbia raggiunto la dimensione
# limite stabilita per la masterizzazione e restituisce 1 o 0 a seconda che si sia
# raggiunto o no tale limite

local busydim=$(du -k --max-depth 0 $isodir | cut -f1)
# let "busydim=1024*100*$i"

if (( $busydim >= $isodim )) || (( $k >= $line )); then
	k=0
	return 1
else
	return 0
fi

}

function crea_iso ()
{
# la funzione crea_iso non fa altro che convertire in un'immagine iso la directory
# $isodir e successivamente attende verifica che la dimensione finale sia inferiore al
# limite di capienza del supporto
mkisofs -r -V $(basename $isoname .iso) -o $imgdir/$isoname $isodir >> $tempdir/"$isoname"_output 2>&1

# prima di proseguire, controllo che l'immagine esista
if [ -e $imgdir/$isoname ]; then
	local imgdim=$(du -k $imgdir/$isoname | cut -f1)
else
	echo "=========================================================================="
	echo "Per qualche strano motivo, l'immagine non è stata creata."
	echo ""
	echo "Mi dispiace, ma il backup si interrompe qui; controlla cosa è andato"
	echo "storto e riprendi con \"$(basename $0) --resume\""
	echo "=========================================================================="
	exit 1
fi

# riordino per dimensione le liste dei file e delle directory
cat $okdir | sort -nr -o $okdir
cat $sparefiles | sort -nr -o $sparefiles

# aggiorno le copie di backup delle liste
cp -f $okdir $tempdir/backup_$(basename $okdir)~
cp -f $sparefiles $tempdir/backup_$(basename $sparefiles)~

# per sicurezza, controllo che la dimensione effettiva dell'immagine sia inferiore al
# limite massimo
if [ "$imgdim" -le "$maxdim" ]; then
	return 0
else
	return 1
fi
}

# =======================================================================================
# fine dichiarazione delle funzioni
# =======================================================================================

# =======================================================================================
# inizio programma principale
# =======================================================================================
# inizializzo variabili di path per comandi non residenti nel path di base
otbin=~/bin

# inizializzo le variabili $n e $tempdire quelle non dipendenti da queste due.
# Le altre devono essere inizializzate dopo che si è scelta la funzione da utilizzare
k=0					# indice riempimento
m=0					# indice file multipli
n=1					# indice nome backup
# i=0					# indice di riempimento virtuale
tempdir=~/tmp/$($otbin/tempname)	# directory temporanea
imgdir=~/backup				# directory delle immagini ISO
filetemp=~/tmp/$($otbin/tempname)	# file temporaneo
confile=config				# file di resume
backfile=".backntar.conf"		# file di configurazione

# prelevo la funzione da effettuare, dal primo argomento
funzione="$1"

# controllo che mi sia stato ordinato di procedere in modalità "quiet", ossia creando
# tutte le immagini ISO di seguito
quiet=$(echo "$*" | grep quiet)
if [ "$quiet" ]; then
	quiet="yes"
else
	quiet="no"
fi

case $funzione in
	-h | --help)	dohelp;;
	-c | --conf)	doconf;;
	-f | --file)	preleva_conf;;
	-s | --save)	preleva_dati $2 $3 $4 $5 $6;;
	-r | --resume)	preleva_resume $2 $3;;
	*)		echo "Spiacente, ma la funzione \"$funzione\" non esiste."
			echo "Prova a digitare \"$(basename $0) --help\" per ottenere aiuto."
			exit 1;;
esac

# inizializzo le altre variabili: se si è in resume, la variabile $tempdir
# e la variabile $n sono state riassegnate
okdir=$tempdir/okdir			# elenco $okdir
kodir=$tempdir/kodir			# elenco $kodir
sparefiles=$tempdir/spare		# elenco $sparefiles
isodir=$tempdir/isodir			# directory immagine

#inizializzo i file e le directory necessarie
if [ ! -e $tempdir ]; then
	mkdir -p $tempdir
	mkdir -p $isodir
	mkdir -p $imgdir
fi

# verifico che la creazione sia andata a buon fine
if [ ! -e $tempdir -o ! -e $isodir -o ! -e $imgdir ]; then
	echo "Per qualche motivo non ho potuto creare le directory
necessarie, quindi termino qui il compito, per evitare di far danno!
Spiacente!!!
"
	exit 1
fi

# controllo che i dati inseriti siano coerenti
se_corretta_sintassi

# calcolo la dimensione totale della directory $backdir e il numero approssimativo
# di supporti da utilizzare
totdim=$(du -k --max-depth 0 $backdir | cut -f1)
let "ndvd=($totdim/1024)/($maxdim)+1"

# stampo a video la configurazione attuale
echo "*************************************************************************"
echo "Sarà effettuato il backup completo della directory $backdir"
echo "La dimensione dell'immagine ISO è impostata a $isodim MB"
echo "La dimensione ottimale è impostata a $optdim MB"
echo "La dimensione dei supporti è impostata a $maxdim MB"
echo "*************************************************************************"
echo "Saranno necessari approssimativamente $ndvd supporti"
echo "*************************************************************************"
echo ""
echo ""

# riporto i MB in KB
let "optdim=$optdim*1024"
let "isodim=$isodim*1024"
let "maxdim=$maxdim*1024"

# creo la lista dei file e delle directory, a meno che non tratti di un resume
# per cui copio i file di backup nelle liste per evitare di tralasciare alcuni
# file
if [ "$work" != "resume" ]; then
	echo -n "Sto creando la lista delle directory e dei file..."
	crea_lista 
	echo "terminato!"
elif [ "$work" = "resume" ]; then
	cp -f $tempdir/backup_$(basename $okdir)~ $okdir
	cp -f $tempdir/backup_$(basename $sparefiles)~ $sparefiles
fi

# creo le immagini ISO necessarie al backup della directory $backdir. Finché gli elenchi
# $okdir e $sparefiles non sono vuoti, sarà necessario creare altre immagini ISO;
# andranno aggiunti file e directory alla stessa immagine, finché questa non raggiunge
# la dimensione fissata. Se una directory non entra, perché è troppo grossa per lo spazio
# restante, allora si esamina il file più grande, poi la seconda directory più grande e
# così via.

echo "Procedo alla creazione delle immagini ISO..."
echo "Per visualizzare i progressi, entra in una shell e dai il comando"
echo "tail -f "$tempdir"/tar_output"

while [ -s $okdir -o -s $sparefiles ]; do
	isoname="backup_$(date -d "today" +%Y%m%d)_$n.iso"
	echo -e "\tCreo l'immagine $isoname..."
	while se_pieno; do
		if se_entra $okdir; then
			echo -en "\t\tSto comprimendo la directory"
			comprimi $okdir
# 			let "i=$i+1"
			k=0
			echo " terminato!"
		elif se_entra $sparefiles; then
			echo -en "\t\tSto comprimendo il file"
			comprimi $sparefiles
# 			let "i=$i+1"
			k=0
			echo " terminato!"
		fi
		if [ ! -s $okdir -a ! -s $sparefiles ]; then
			break
		fi
		let "k++"
	done
	echo "Sto creando l'immagine ISO $isoname..."
	echo "Per visualizzare i progressi, entra in una shell e dai il comando"
	echo "tail -f "$tempdir"/"$isoname"_output"
	crea_iso
	let "n++"
	rm -f $isodir/*
# 	i=0
	echo -e "\tterminato!"
	echo "--> E' stata creata l'immagine ISO $isoname nella directory $imgdir,"
	echo "--> per cui si prega di procedere alla masterizzazione prima di proseguire."
	echo "--> Io restero' in attesa che tu mi dica \"prosegui\"."
	while true; do
		if [[ $quiet = "no" ]]; then
			read scelta
			if [ "$scelta" = "prosegui" ]; then
				break
			elif [ "$scelta" = "termina" ]; then
				echo "Rinominerò la cartella \"$tempdir\" in \"backup_$(date -d "today" +%Y%m%d)\""
				echo "così che tu possa riconoscerla facilmente"
				mv $tempdir $(dirname "$tempdir")/backup_$(date -d "today" +%Y%m%d)
				exit 0
			else
				echo "Scegli \"prosegui\" per continuare nella procedura di backup"
				echo "Scegli \"termina\" per terminare la procedura di backup"
				echo "Puoi sempre riprendere più tardi con \"$(basename $0) --resume\""
			fi
		elif [[ $quiet = "yes" ]]; then
			break
		fi
	done
	scelta=""
done

echo "terminato!"

exit 0
# =======================================================================================
# fine programma principale
# =======================================================================================
  • Data: 21/10/2007
  • Autore: Tiferet
Strumenti personali
Namespace

Varianti