Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 25/06/2008, à 23:29

sebk

bug entre tar et xargs [résolus]

Bonjour,

Je suis en train de réaliser un script de sauvegarde des différents homes de mon ubuntu sur un serveur ftp distant (ma freebox en fait).

Tout est au point sauf un petit détail : lorsqu'un fichier contiends un double espace (notament des sauvegardes de page web), tar concatène les deux espace en un seul et ne trouve donc pas le fichier.

J'ai bien trouvé un moyen de contourner ça en mettant des quotes mais le soucis c'est que pour créer la commande, je suis obligé d'utiliser un xargs pour exploiter le résultat de la commande find.

Petite précision pour ceux qui me répondrons que je n'ai qu'à faire un tar d'un répertoire tout simplement, c'est que j'ai des règles d'exception paramétrable et que je retravail donc le résultat du find.

La commande que j'utilise est la suivante :
sudo -u $usersb cat /tmp/save_fichiers.log | xargs tar -rf /tmp/$nom_archive.tar 2> /tmp/save_tar.log


Quelqu'un aurait-il une idée de comment je peux contourner cela ?

Dernière modification par sebk (Le 10/07/2008, à 22:44)


Iceberg Project : www.iceberg-linux.net

Hors ligne

#2 Le 26/06/2008, à 12:09

Totor

Re : bug entre tar et xargs [résolus]

peux-tu poster ta commande initiale (find + tar) ?


-- Lucid Lynx --

Hors ligne

#3 Le 26/06/2008, à 17:54

sebk

Re : bug entre tar et xargs [résolus]

Voici mon script complet

#!/bin/bash

renice -20 $$

if [ "$1" != "" ]
then
	config="$1"
else
	config="/home/seb/.script/save.conf"
fi
config=`echo $config | sed "s/ /\\\ /g"`

if [ ! -f $config ]
then
	echo "`date` : Lecture des paramètres impossible" > save.log
	exit 1
fi

echo "`date` : Lecture des paramètres..." > save.log

# lecture du nom de l'archive
usersb=`bash /home/seb/.script/config_reader.sh "$config" user`
if [ "$usersb" = "" ]
then
	usersb="root"
fi
echo "substitution : $usersb"

# lecture des répertoires à sauvegarder
bash /home/seb/.script/config_reader.sh $config save-path > /tmp/save_path.tmp

# lecture des trames de fichier à exclure
bash /home/seb/.script/config_reader.sh $config exclude > /tmp/save_exclude.tmp

# lecture des trames à inclure malgrès tout
bash /home/seb/.script/config_reader.sh $config force-include > /tmp/save_include.tmp

# lecture du nom de l'archive
nom_archive=`bash /home/seb/.script/config_reader.sh $config nom-archive`
if [ "$nom_archive" = "" ]
then
	exit 1
fi

# lecture de la chaine de connexion
site=`bash /home/seb/.script/config_reader.sh $config site`
if [ "$nom_archive" = "" ]
then
	exit 1
fi
#site=`echo $site | sed "s/ /\\\ /"`

echo "`date` : Début du traitement de sauvegarde" > save.log

# raz log des fichiers
echo "" > /tmp/save_fichiers.log

# raz de l'archive si elle existe
rm /tmp/$nom_archive.tar

# archivage de la dernière archive valide
parm="$site"
i=0
user=""
password=""
server=""
path=""
tmp=""
if [ -f "/tmp/ok_$nom_archive" ]
then
	# décomposition du paramètre
	while [ $i -lt ${#parm} ]
	do
		# récuparation du user
		if [ "$user" = "" ]
		then
			if [ "${parm:i:1}" != ":" ]
			then
				tmp="$tmp${parm:i:1}"
			else
				user="$tmp"
				tmp=""
				i=`expr $i + 1`
			fi
		fi
	
		# récuparation du mot de passe
		if [ "$user" != "" -a "$password" = "" ]
		then
			if [ "${parm:i:1}" != "@" ]
			then
				tmp="$tmp${parm:i:1}"
			else
				password="$tmp"
				tmp=""
				i=`expr $i + 1`
			fi
		fi
	
		# récuparation du serveur
		if [ "$user" != "" -a "$password" != "" -a "$server" = "" ]
		then
			if [ "${parm:i:1}" != "/" ]
			then
				tmp="$tmp${parm:i:1}"
			else
				server="$tmp"
				tmp=""
			fi
		fi
	
		# récuparation du fichier
		if [ "$user" != "" -a "$password" != "" -a "$server" != "" ]
		then
			path="$path${parm:i:1}"
		fi
	
		i=`expr $i + 1`
	done
	
ftp -nv $server << SCRIPT
quote user $user
quote pass $password
delete "$path/$nom_archive.tar.gz.old"
rename "$path/$nom_archive.tar.gz" "$path/$nom_archive.tar.gz.old"
quit
SCRIPT

	rm -f "/tmp/ok_$nom_archive"
fi

# pour chaque répertoire
while read rep
do
	sudo -u $usersb find $rep | sed "s/\\\\/\\\\\\\\/g" | sed "s/\\ /\\\\ /g" > /tmp/save_find.tmp
	# pour chaque fichier
	while read fichier
	do
		if [ -f "$fichier" ]
		then
			exclusion="non"			
			# test la trame d'exclusion
			while read exclus
			do
				if [ "`echo $fichier | sed -n \"/$exclus/p\"`" != "" ]
				then
					exclusion="oui"
				fi
			done < /tmp/save_exclude.tmp
		
			# test si la trame est à inclure malgrès tout
			while read inclus
			do
				if [ "`echo $fichier | sed -n \"/$inclus/p\"`" != "" ]
				then
					exclusion="non"
				fi
			done < /tmp/save_include.tmp

			# si le fichier n'est pas exclus
			if [ "$exclusion" = "non" ]
			then
				# Création de la liste des fichiers
				fichier=`echo $fichier | sed "s/\"/\\\\\"/g"`
				echo "\"$fichier\""  >> /tmp/save_fichiers.log
			fi
		fi
	done < /tmp/save_find.tmp
done < /tmp/save_path.tmp

# création de l'archive
rm -f /tmp/$nom_archive.tar
sudo -u $usersb cat /tmp/save_fichiers.log | xargs tar -rf /tmp/$nom_archive.tar 2> /tmp/save_tar.log
cat /tmp/save_tar.log | grep -v "tar: Suppression de « / » au début des noms des membres" >> /tmp/save.log

# compression
echo "`date` : Début de la compression de l'archive" >> /tmp/save.log
rm /tmp/$nom_archive.tar.gz
gzip -9 /tmp/$nom_archive.tar 2>> /tmp/save.log
echo "`date` : Fin de la compression de l'archive" >> /tmp/save.log

# envois ftp
cd /tmp
i=1
echo "envois"
echo "`date` : envoi ftp essai n°$i" >> /tmp/save.log
wput --reupload --dont-continue -B "$nom_archive.tar.gz" "ftp://$site" >> /tmp.save.log 2>> /tmp/save.log
i=`expr $i + 1`
while [ `ls -l "$nom_archive.tar.gz" | awk '{ print $5 }'` -ne `bash /home/seb/.script/ftp_get_size.sh "$site$nom_archive.tar.gz"` -a $i -le 3 ]
do
	echo "`date` : envoi ftp essai n°$i" >> /tmp/save.log
	wput --reupload --dont-continue -B "$nom_archive.tar.gz" "ftp://$site" >> /tmp.save.log 2>> /tmp/save.log
	i=`expr $i + 1`
done

if [ $i -le 3 ]
then
	echo "`date` : Envoi de l'archive terminée" >> /tmp/save.log
	echo "ok" > /tmp/ok_$nom_archive
else
	echo "`date` : Envoi de l'archive a échoué" >> /tmp/save.log
	echo "" > "/home/seb/Bureau/`date` - save echoue"
fi

# suppression des fichiers temporaires
rm /tmp/save_path.tmp
rm /tmp/save_find.tmp
rm /tmp/save_exclude.tmp
rm /tmp/save_include.tmp

Dernière modification par sebk (Le 26/06/2008, à 17:55)


Iceberg Project : www.iceberg-linux.net

Hors ligne

#4 Le 30/06/2008, à 22:26

sebk

Re : bug entre tar et xargs [résolus]

Si il y en a qui trouve mon code abscon (le shell script il est vrai est puissant mais pas très lisible) voici comment reproduire le bug :

Créer un fichier "toto.txt"
Créer un fichier "to\ \ to.txt" (deux espaces)
Créer un fichier "test.txt" qui contiendra le mon des deux fichiers (un par ligne)
Puis effectuer un : cat test.txt | xargs tar -cf archive.txt

Le deuxième fichier est en erreure


Iceberg Project : www.iceberg-linux.net

Hors ligne

#5 Le 08/07/2008, à 18:06

sebk

Re : bug entre tar et xargs [résolus]

Y'a quelqu'un ?


Iceberg Project : www.iceberg-linux.net

Hors ligne

#6 Le 08/07/2008, à 20:11

Totor

Re : bug entre tar et xargs [résolus]

je vais essayer de passer du temps sur ton pb demain sur mon temps de travail (si la solution n'a pas été trouvé d'ici là).
j'ai juste une petite question : pourquoi lances-tu toutes tes commandes via bash alors que ton script inclu : "#!/bin/bash" ? (je ne sais plus comment s'appelle cette ligne !)


-- Lucid Lynx --

Hors ligne

#7 Le 08/07/2008, à 20:21

sebk

Re : bug entre tar et xargs [résolus]

le shebang je crois (je ne suis plus sûr de l'ortograf)

en fait je n'ai appris qu'il y a deux jours qu'on pouvais lancer un shell directement sans commande bash (et même supprimer le ".sh" pas beau) en cherchant à intégrer un script dans le système proprement


Iceberg Project : www.iceberg-linux.net

Hors ligne

#8 Le 09/07/2008, à 08:49

Totor

Re : bug entre tar et xargs [résolus]

remplace ta ligne :

sudo -u $usersb cat /tmp/save_fichiers.log | xargs tar -rf /tmp/$nom_archive.tar 2> /tmp/save_tar.log

par :

sudo -u $usersb cat /tmp/save_fichiers.log | xargs -i{} tar -rf /tmp/$nom_archive.tar "{}" 2> /tmp/save_tar.log

le -i de xargs te permet de spécifier la chaine de caractère remplaçant tes arguments.

J'espère avoir répondu à ta question !

EDIT :
tu aurais pu utiliser l'option -exec de la commande find.

find <conditions de sélection> -exec tar rf /tmp/$nom_archive.tar "{}" \;

ce qui reviens exactement au même wink

Dernière modification par Totor (Le 09/07/2008, à 09:38)


-- Lucid Lynx --

Hors ligne

#9 Le 09/07/2008, à 22:15

sebk

Re : bug entre tar et xargs [résolus]

Merci pour ta réponse

Je viens de tester ta solution et j'ai dut planter le traitement au bout de deux heures...

Tes solutions comportent le même problème que la première version de mon programme, à savoir que dans les deux cas, au lieu de faire un "tar -rf fichier1 fichier2 fichier3...", il fait :
tar -rf fichier1
tar -rf fichier2
...

a prioris ces solutions semblent revenir au même sauf au niveau performances :
- dans la solution 1 le tar ne prend pas la peine d'analyser l'archive à chaque fichier ==> une archive de 4Go se fait en une heure sur mon poste
- dans la solution 2 chaque tar analyse l'archive à chaque fichier et au bout de deux heures il en est à 1Go et prend de plus en plus de temps au fure et à mesure que l'archive grossit

En tout cas je retiends le xargs -i : ça peut être très util dans certains cas


Iceberg Project : www.iceberg-linux.net

Hors ligne

#10 Le 09/07/2008, à 22:55

Totor

Re : bug entre tar et xargs [résolus]

Pour avoir l'ensemble des fichiers sur une seule ligne, essaie ceci (j'ai pas testé mais au pire,c'est une piste) :

sudo -u $usersb cat /tmp/save_fichiers.log | sed 's/ /\\ /g'|xargs echo tar rf /tmp/$nom_archive.tar|bash

Dernière modification par Totor (Le 09/07/2008, à 22:56)


-- Lucid Lynx --

Hors ligne

#11 Le 10/07/2008, à 20:11

sebk

Re : bug entre tar et xargs [résolus]

Merci pour ton idée ! (j'aurais jamais pensé au pipe bash tout seul)

Après quelques essais voici la commade finale qui marche dans tous les cas :

cat /tmp/save_fichiers.log | sed "s/'/\\\\'/g" | sed "s/ /\\\\ /g" | sed "s/\"/\\\\\"/g" | xargs echo tar --ignore-failed-read -rf toto.tar | bash

Je m'empresse de mettre un joli résolus sur mon article


Iceberg Project : www.iceberg-linux.net

Hors ligne

#12 Le 10/07/2008, à 20:17

Totor

Re : bug entre tar et xargs [résolus]

note : pour "alleger" tes sed, tu peux les remplacer par :

sed "s/'/\\\\'/g;s/ /\\\\ /g;s/\"/\\\\\"/g"

Dernière modification par Totor (Le 10/07/2008, à 20:18)


-- Lucid Lynx --

Hors ligne

#13 Le 10/07/2008, à 22:45

sebk

Re : bug entre tar et xargs [résolus]

c'est bon à savoir

Encore merci


Iceberg Project : www.iceberg-linux.net

Hors ligne