BASH : stderr : code d'erreur enregistré dans une variable (comportement) Le sujet est résolu

Tout ce qui concerne la programmation.
Répondre
Avatar du membre
dezix
Modérateur
Modérateur
Messages : 992
Enregistré le : 04 juin 2016, 14:50
Diaspora* : dezix@framasphere.org
Status : En ligne

14 juil. 2020, 19:06

Bonjour,

J'ai besoin d'un petit coup de main pour comprendre un comportement de bash qui m'échappe :017:

Pour un script qui au final doit exécuter la commande :

rsync -rulptgomv --del --backup --backup-dir="$backup" --log-file="$rsync_log" --exclude-from="$exclude" "$source" "$destination"


Ce script en plus de la commande rsync (c'est sa raison d'être) renvoie des infos sur le terminal et enregistre sur 2 fichiers de log :
  • script.log qui liste sommairement les exécutions successives pour s'y retrouver facilement
  • rsync.log qui enregistre en plus le produit de --log-file=

Pour le débogage je remplace cette commande par : rm fake
ce qui me permet de tester mon script en plaçant ou non le fichier "fake" dans le répertoire courant.

Pour les débutants (un poil plus que moi ;-) je rappelle que :

s'il n'y a pas de fichier "fake" la sortie d'erreur = 1

Code : Tout sélectionner

$ rm fake
rm: impossible de supprimer 'fake': Aucun fichier ou dossier de ce type
$ state="$?"
$ echo "$state"
1

sinon, "fake" est supprimé et la sortie d'erreur = 0

Code : Tout sélectionner

$ rm fake
$ state="$?"
$ echo "$state"
0


Dans mon script test ça donne :

Code : Tout sélectionner

#!/bin/bash
# extrait du script
# ....
echo "Commande <rm> de simulation d'erreur" ;	# test basé sur la (non)présence du fichier "fake"
rm "$destination"/fake 2> "$tmp"/error.txt && state="$?"	\
 && echo -e "\n\n<rm> : commande terminée sans erreur — $state" >> "$log1"	\
 || echo -e "\n\n<rm> a rencontré un problème : 		\
		\nERROR  — code : "$state"		\
		\n\t$(cat "$tmp"/error.txt)" >> "$log1" ;
#
#
# Messsage Sortie Rsync pour script.log
if [ "$state" = 0 ] ;
	then
		echo -e "\n\trsync a été exécuté sans problème => OK!" | tee -a "$log2" ;
	else
		echo -e "\n\trsync  a rencontré un problème => error $state" ;
		echo -e "\n\tLe script DATA-Rsync est prématurément interrompu	\
			\n\tdes modifications ont pu être faites sur la sauvegarde	\
			\n\tune intervention manuelle risque d'être nécéssaire... :((" | tee -a "$log2" ;
		exit 1 ;						# état 1 pour Notification de bureau (cmde lanceur)
fi
#
####	suite du script		####################
À ce stade,

si la commande (rm) ne produit pas d'erreur, j'ai bien dans mon log :
<rm> : commande terminée sans erreur — 0

mais si le fichier "fake" est manquant, cela donne :
<rm> a rencontré un problème :
ERROR -- code :
rm: impossible de supprimer '/home/dezix/tests/rsync_test/dest/fake': Aucun fichier ou dossier de ce type
où le code de sortie d'erreur est manquant.

Je suis certain que la variable $state est vide,
c'est probablement en lien avec : 2> "$tmp"/error.txt

mais je n'ai pas idée de comment corriger cela. :blush:


Merci pour votre aide.
Debian testing/stable - XFCE
MicP
Modérateur
Modérateur
Messages : 615
Enregistré le : 16 avr. 2016, 22:14
Status : Hors ligne

14 juil. 2020, 21:06

Bonjour

Essaye plutôt comme ça :

Code : Tout sélectionner

#!/bin/bash
# extrait du script
# ....

echo "Commande <rm> de simulation d'erreur";    # test basé sur la (non)présence du fichier "fake"
rm "$destination"/fake 2> "$tmp"/error.txt; state=$?; [ $state = 0 ]      \
&& echo -e "\n\n<rm> : commande terminée sans erreur — $state" >> "$log1" \
|| echo -e "\n\n<rm> a rencontré un problème : 		                  \
              \nERROR  — code : $state                                    \
              \n\t$(cat "$tmp"/error.txt)" >> "$log1" ;
#
#
# Messsage Sortie Rsync pour script.log
if [ $state = 0 ];
    then
	echo -e "\n\trsync a été exécuté sans problème => OK!" | tee -a "$log2" ;
    else
	echo -e "\n\trsync  a rencontré un problème => error $state" ;
	echo -e "\n\tLe script DATA-Rsync est prématurément interrompu  \
	    \n\tdes modifications ont pu être faites sur la sauvegarde  \
	    \n\tune intervention manuelle risque d'être nécéssaire... :((" | tee -a "$log2" ;
	exit 1 ;						# état 1 pour Notification de bureau (cmde lanceur)
fi
#
####	suite du script		####################
Avatar du membre
dezix
Modérateur
Modérateur
Messages : 992
Enregistré le : 04 juin 2016, 14:50
Diaspora* : dezix@framasphere.org
Status : En ligne

15 juil. 2020, 00:14

Salut !
MicP a écrit :
14 juil. 2020, 21:06
Essaye plutôt comme ça....
Oui, ça fonctionne :023:

Du coup, les opérateurs de contrôle && et || sont sur la sortie du test et non sur la commande initiale.

J'en prends bonne note.

Merci pour le tuyau !

:006:
Debian testing/stable - XFCE
MicP
Modérateur
Modérateur
Messages : 615
Enregistré le : 16 avr. 2016, 22:14
Status : Hors ligne

15 juil. 2020, 15:01

Oui
sinon, tels que tu les avais mis,

Si le fichier fake a pu être supprimé, l'opération d'assignation state="$?" est exécutée,
et c'est le code d'erreur de cette opération d'assignation qui est pris en compte ensuite par les opérateurs && et || qui suivent l'opération d'assignation.

Si le fichier fake n'a pas pu être supprimé, l'opération d'assignation d'une valeur à la variable state n'est pas faite,
donc, la variable state reste vide, le code d'erreur reste celui de la commande rm et c'est seulement ce qui suit le || qui est exécuté.
MicP
Modérateur
Modérateur
Messages : 615
Enregistré le : 16 avr. 2016, 22:14
Status : Hors ligne

16 juil. 2020, 13:52

Tu peux aussi l'écrire comme ça :

Code : Tout sélectionner

#!/bin/bash
# extrait du script
# ....

echo "Commande <rm> de simulation d'erreur"   # test basé sur la (non)présence du fichier "fake"

if rm "$destination"/fake 2> "$tmp"/error.txt
then
    echo -e "\n\n<rm> : commande terminée sans erreur — $?" >> "$log1"
    echo -e "\n\trsync a été exécuté sans problème => OK!" | tee -a "$log2"
else
    echo -e "\n\n<rm> a rencontré un problème :\nERROR  — code : $?\n\t$(cat "$tmp"/error.txt)" >> "$log1"
    echo -e "\n\tLe script DATA-Rsync est prématurément interrompu\n\tdes modifications ont pu être faites sur la sauvegarde\n\tune intervention manuelle risque d'être nécessaire... :((" | tee -a "$log2"
    exit 1    # état 1 pour Notification de bureau (cmde lanceur)
fi
Avatar du membre
dezix
Modérateur
Modérateur
Messages : 992
Enregistré le : 04 juin 2016, 14:50
Diaspora* : dezix@framasphere.org
Status : En ligne

16 juil. 2020, 15:07

Merci pour toutes ces bonnes infos.

Je ne savais pas que l'on pouvait créer une boucle directement sur la sortie d'erreur d'une commande.

Bien sûr, après coup, c'est logique... mais je n'y avais jamais pensé.

C'est toute la difficulté d'apprendre sur le tas/tard

:good:
Debian testing/stable - XFCE
Répondre