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 19/11/2017, à 00:29

Arbiel

[Résolu] bash : "exit" n'arrête pas l'interpréteur

Bonsoir

Je ne comprends pas le déroulement de ce script

#! /bin/bash
	function init_gbl {
		function rep_ucg {
# cette fonction n'est a priori pas accessible en dehors de init_gbl, or ce n'est pas le cas. Pourquoi ?
			rep="${UCG_DIR:-"/home/.ucg"}";
			if [[ -d "${rep}" ]] ; then
# retrait de l'éventuel "/" qui peut être présent en fin du nom du répertoire
				sed -r "s|^(.+)/$|\1|" <<<"${rep}" ;
			else
				echo "${rep} est un fichier ; arrêt immédiat" ;
				exit 1 ;
				echo "Cette commande ne doit pas être exécutée";
			fi;
		}
		Gbl_dir_ucg="$(rep_ucg)";
		echo $?
	}
	
		function test {
		echo "ucg : Le script ne s'est pas arrêté.";		gbl_test=true;
	}
	set -o xtrace
	init_gbl
	lg="fr"
# bash devrait m'indiquer qu'il ne connaît pas rep_ucg, fonction locale de init_gbl
	alphabet="$(rep_ucg)/Greek-coptic-extended.${lg}";
	echo $?
	echo "${alphabet}"
	
"${@}";

dont voici la trace d'exécution

remi@remi-Vostro-3550:~$ env UCG_DIR=/tmp/fichier ~/Bureau/test test
+ init_gbl
++ rep_ucg
++ rep=/tmp/fichier
++ [[ -d /tmp/fichier ]]
++ echo '/tmp/fichier est un fichier ; arrêt immédiat'
++ exit 1
+ Gbl_dir_ucg='/tmp/fichier est un fichier ; arrêt immédiat'
+ echo 1
1
+ lg=fr
++ rep_ucg
++ rep=/tmp/fichier
++ [[ -d /tmp/fichier ]]
++ echo '/tmp/fichier est un fichier ; arrêt immédiat'
++ exit 1
+ alphabet='/tmp/fichier est un fichier ; arrêt immédiat/Greek-coptic-extended.fr'
+ echo 1
1
+ echo '/tmp/fichier est un fichier ; arrêt immédiat/Greek-coptic-extended.fr'
/tmp/fichier est un fichier ; arrêt immédiat/Greek-coptic-extended.fr
+ test
+ echo 'ucg : Le script ne s'\''est pas arrêté.'
ucg : Le script ne s'est pas arrêté.
+ gbl_test=true
remi@remi-Vostro-3550:~$ env UCG_DIR=/tmp/fichier ~/Bureau/test test
+ init_gbl
++ rep_ucg
++ rep=/tmp/fichier
++ [[ -d /tmp/fichier ]]
++ echo '/tmp/fichier est un fichier ; arrêt immédiat'
++ exit 1
+ Gbl_dir_ucg='/tmp/fichier est un fichier ; arrêt immédiat'
+ echo 1
1
+ lg=fr
++ rep_ucg
++ rep=/tmp/fichier
++ [[ -d /tmp/fichier ]]
++ echo '/tmp/fichier est un fichier ; arrêt immédiat'
++ exit 1
+ alphabet='/tmp/fichier est un fichier ; arrêt immédiat/Greek-coptic-extended.fr'
+ echo 1
1
+ echo '/tmp/fichier est un fichier ; arrêt immédiat/Greek-coptic-extended.fr'
/tmp/fichier est un fichier ; arrêt immédiat/Greek-coptic-extended.fr
+ test
+ echo 'ucg : Le script ne s'\''est pas arrêté.'
ucg : Le script ne s'est pas arrêté.
+ gbl_test=true
remi@remi-Vostro-3550:~$ 

D'après le manuel, si je le comprends bien, le script devrait s'arrêter à l'appel de "exit 1"

manuel bash a écrit :

exit

    exit [n]

    Exit the shell, returning a status of n to the shell’s parent. If n is omitted, the exit status is that of the last command executed. Any trap on EXIT is executed before the shell terminates.

ensuite, la commande

alphabet="$(rep_ucg)/Greek-coptic-extended.${lg}";

devrait provoquer le message : commande inconnue puisque rep_ucg est une fonction locale de init_gbl.

Le fait qu'elle ait été préalablement été appelée lors de l'exécution de init_gbl a-t-il un impact ?

Merci d'avance pour vos éclaircissements.

Dernière modification par Arbiel (Le 22/11/2017, à 16:17)


Arbiel Perlacremaz
LDLC Aurore NK3S-8-S4 Ubuntu 20.04
Abandon d'azerty au profit de bépo, de google au profit de Lilo et de la messagerie électronique violable au profit de Protonmail, une messagerie chiffrée de poste de travail à poste de travail.

Hors ligne

#2 Le 19/11/2017, à 01:18

Watael

Re : [Résolu] bash : "exit" n'arrête pas l'interpréteur

salut,

exit est exécuté dans un sous-shell.
il quitte donc le sous-shell, pas script !

je n'ai jamais lu que les fonctions pouvaient être locales.


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#3 Le 19/11/2017, à 08:09

pingouinux

Re : [Résolu] bash : "exit" n'arrête pas l'interpréteur

Bonjour,
Dans l'exemple suivant, A est exécutée dans le shell courant (comme dans ton cas), et B dans un sous-shell.

function A { function a { echo dans function a; }; echo dans A; }
function B {( function b { echo dans function b; }; echo dans B; )} 

type A B 
type a b
A; B
type a b

En voici le résultat :

A is a function
A () 
{ 
    function a () 
    { 
        echo dans function a
    };
    echo dans A
}
B is a function
B () 
{ 
    ( function b () 
    { 
        echo dans function b
    };
    echo dans B )
}
./y: line 5: type: a: not found
./y: line 5: type: b: not found
dans A
dans B
a is a function
a () 
{ 
    echo dans function a
}
./y: line 7: type: b: not found

Ajouté : Test du exit, qui semble fonctionner

function A { 
   function a { echo dans function a; if false;then exit 1;else exit 2;fi; } 
   echo dans A
}

A
echo avant appel a
a
echo $? après appel a

Résultat

dans A
avant appel a
dans function a

Ajouté (2) : J'ai enfin compris… smile
C'est à cause de cette ligne

alphabet="$(rep_ucg)/Greek-coptic-extended.${lg}";

que rep_ucg est exécuté dans un sous-shell, comme le dit Watael.

Dernière modification par pingouinux (Le 19/11/2017, à 10:18)

Hors ligne

#4 Le 19/11/2017, à 18:47

Arbiel

Re : [Résolu] bash : "exit" n'arrête pas l'interpréteur

Bonsoir

Merci beaucoup pour ces explications. Elles reprennent des informations présentes dans le manuel, que j'ai pourtant lu à maintes reprises, mais, je dois dire, sans en digérer vraiment le contenu.

Watael a écrit :

je n'ai jamais lu que les fonctions pouvaient être locales.

Effectivement, rien de tel n'est écrit dans le manuel. J'avais tiré cette conclusion de tests dont j'avais visiblement mal interprété les résultats.

Je comprends maintenant que, comme

le manuel bash a écrit :

3.1.1 Shell Operation

The following is a brief description of the shell’s operation when it reads and executes a command. Basically, the shell does the following:

     Executes the command (see Executing Commands).
    Optionally waits for the command to complete and collects its exit status (see Exit Status).

et que

le manuel bash a écrit :

Shell functions are a way to group commands for later execution using a single name for the group

lors de l'exécution de la commande "function nom" ou de "nom ()", bash lis et analyse syntaxiquement le code de la fonction et le mémorise pour exécution ultérieure. Les fonctions qui y sont définies ne sont connues que lors de l'exécution de nom, et ceci dans l'environnement d'exécution courant. En reprenant l'exemple de pingoinlinux, j'ai vérifié qu'avec la commande "(A ; B)" au lieu de "A ; B", les fonction a et b restent inconnues dans le contexte d'origine.

Il reste à comprendre dans quel cas, sauf obligation par bash (expansion de commandes ou pipeline - à l'exception éventuelle de la dernière portion), il est intéressant de faire exécuter des commandes dans un sous-shell.

Pour ce qui concerne ma manière de programmer, je vais revenir sur l'habitude que j'ai prise de définir des fonctions au sein d'autres fonctions, ce qui était pour moi le moyen d'en restreindre le domaine d'utilisation, alors qu'il n'en est absolument rien.

Merci encore pour vos explications


Arbiel Perlacremaz
LDLC Aurore NK3S-8-S4 Ubuntu 20.04
Abandon d'azerty au profit de bépo, de google au profit de Lilo et de la messagerie électronique violable au profit de Protonmail, une messagerie chiffrée de poste de travail à poste de travail.

Hors ligne