#1 Le 18/11/2017, à 23: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"
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, à 15:17)
Arbiel Perlacremaz
LDLC Aurore NK3S-8-S4 Ubuntu 20.04, GNOME 3.36.8
24.04 en cours de tests
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, à 00: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.
En ligne
#3 Le 19/11/2017, à 07: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…
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, à 09:18)
Hors ligne
#4 Le 19/11/2017, à 17: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.
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
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
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, GNOME 3.36.8
24.04 en cours de tests
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