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

Tout ce qui concerne la programmation.
Répondre
Avatar de l’utilisateur
dezix
Membre hyper actif
Membre hyper actif
Messages : 3546
Inscription : 04 juin 2016, 14:50
Status : Hors-ligne

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.
**Simple Utilisateur** -- Debian stable - XFCE
MicP
Modérateur
Modérateur
Messages : 896
Inscription : 16 avr. 2016, 22:14
Status : Hors-ligne

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 de l’utilisateur
dezix
Membre hyper actif
Membre hyper actif
Messages : 3546
Inscription : 04 juin 2016, 14:50
Status : Hors-ligne

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:
**Simple Utilisateur** -- Debian stable - XFCE
MicP
Modérateur
Modérateur
Messages : 896
Inscription : 16 avr. 2016, 22:14
Status : Hors-ligne

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 : 896
Inscription : 16 avr. 2016, 22:14
Status : Hors-ligne

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 de l’utilisateur
dezix
Membre hyper actif
Membre hyper actif
Messages : 3546
Inscription : 04 juin 2016, 14:50
Status : Hors-ligne

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:
**Simple Utilisateur** -- Debian stable - XFCE
Répondre