Appelez un script pour un autre script, mais ne quittez pas le parent si l'enfant appelle exit

11

first.sh:

#! /bin/ksh
echo "prova"
. ./second.sh
echo "ho lanciato il secondo"
. ./third.sh
echo "ho lanciato il terzo"

second.sh:

echo "sono nel secondo script"
dosomething1
exit $?

Si second.shdétecte une erreur et quitte avec le statut -9, first.shquitte toujours. Comment puis-je éviter de quitter le premier shell si le shell enfant se termine?

Je ne peux pas modifier second.sh.

user3589887
la source
Ici, vous utilisez la .commande, qui source un autre fichier dans le shell actuel. Aucun shell enfant ou sous-shell n'est impliqué. Vouliez-vous exécuter second.sh et third.shau lieu de les sourcer?
Celada
oui .. je dois écrire exécuter au lieu de. ./? je veux ignorer "exit $?" dans second.sh .. est possible sans modifier second.sh?
user3589887

Réponses:

13

Ce que vous faites ici est d'inclure second.shet third.shde sous-scripts s'exécuter dans le même processus, qui est appelé «sourcing» dans la programmation shell. . ./second.shest fondamentalement équivalent à inclure le texte de second.shà ce point. La exitcommande quitte le processus, peu importe que vous l'appeliez dans le script d'origine ou dans un script d'origine.

Si tout ce que vous voulez faire est d'exécuter les commandes dans second.shet third.shqu'ils n'ont pas besoin d'accéder ou de modifier des variables et des fonctions à partir du script d'origine, appelez ces scripts en tant que processus enfants.

#! /bin/ksh
echo "prova"
./second.sh
echo "ho lanciato il secondo"
./third.sh
echo "ho lanciato il terzo"

Si vous avez besoin des autres scripts pour accéder aux variables et fonctions à partir du script d'origine, mais pas les modifier, appelez ces scripts en sous-shell. Les sous-coquilles sont des processus distincts, donc exitne les quittent que.

#! /bin/ksh
echo "prova"
(. ./second.sh)
echo "ho lanciato il secondo"
(. ./third.sh)
echo "ho lanciato il terzo"

Si vous devez utiliser des variables ou des fonctions définies dans second.shet third.shdans le script parent, vous devrez continuer à les sourcer.

La commande returnintégrée ne quitte que le script source et non l'ensemble du processus - c'est l'une des rares différences entre l'inclusion d'un autre script avec la .commande et l'inclusion de son texte dans le script parent. Si les scripts d'origine n'appellent exitqu'au niveau supérieur, par opposition aux fonctions internes, vous pouvez alors passer exità return. Vous pouvez le faire sans modifier le script en utilisant un alias.

#! /bin/ksh
echo "prova"
alias exit=return
. ./second.sh
echo "ho lanciato il secondo"
. ./third.sh
unalias exit
echo "ho lanciato il terzo"

Si exitest également appelé à l'intérieur des fonctions, je ne pense pas qu'il existe un moyen non encombrant. Un moyen lourd consiste à définir un piège de sortie et à y mettre votre code.

#!/bin/ksh
do_first () {
  echo "prova"
  trap "after_second" EXIT
  . ./second.sh
  after_second
}
after_second () {
  echo "ho lanciato il secondo"
  trap "after_third" EXIT
  . ./third.sh
  after_third
}
after_third () {
  trap - EXIT
  echo "ho lanciato il terzo"
}
do_first
Gilles 'SO- arrête d'être méchant'
la source
C'est pour cette raison que j'ai cessé d'utiliser "." pour source des fichiers dans un script, et essayez d'utiliser exclusivement «source» à la place. OMI qui devrait être considérée comme une «meilleure pratique» bash, car elle rend beaucoup plus clair ce que fait votre code.
Mark E. Hamilton
6

Au lieu de rechercher le deuxième et le troisième shell, exécutez-les comme vous le feriez pour n'importe quelle autre commande. Le code de sortie peut être stocké et utilisé si vous en avez besoin, comme ceci:

#! /bin/ksh
echo "prova"

# execute and capture stdout ... output of second is not seen ...
OUTPUT1=$(./second.sh)

# find out exit status of second.sh
STATUS1=$?

# ... until now
echo $OUTPUT1

# do something based on the result
if [ $STATUS1 -eq 0 ]; then 
  echo "second.sh ran successfully"
else 
  echo "second.sh crapped out"
fi

# and so on...
Dale Anderson
la source
STATUS1=$?capturera le résultat de la commande echo précédemment émise, qui est indépendante du résultat de ./second.sh.
Cromax
@Cromax, vous avez tout à fait raison. La réponse a été modifiée.
Dale Anderson
0

Essayez-le de cette façon (supprimez d'abord .lors de l'appel second.sh):

first.sh:

#! /bin/ksh
echo "prova"
./second.sh
echo "ho lanciato il secondo"
./third.sh
echo "ho lanciato il terzo"

second.sh:

echo "sono nel secondo script"
dosomething1
exit $?

C'est parce que .c'est un shortcode pour sourcelequel le deuxième script doit être inclus dans le premier.

Mojtaba Rezaeian
la source