Rufen Sie ein Skript für ein anderes Skript auf, aber beenden Sie das übergeordnete Element nicht, wenn das untergeordnete Element exit aufruft

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 $?

Wenn second.shein Fehler erkannt wird und mit dem Status -9 beendet wird, wird first.shimmer beendet. Wie kann ich vermeiden, die erste Shell zu verlassen, wenn die untergeordnete Shell beendet wird?

Ich kann nicht bearbeiten second.sh.

user3589887
quelle
Hier verwenden Sie den .Befehl, der eine andere Datei in der aktuellen Shell bezieht. Es ist keine untergeordnete Shell oder Subshell beteiligt. Wollten Sie sie ausführen second.sh und third.shanstatt sie zu beschaffen?
Celada
ja .. ich muss ausführen statt schreiben. ./? Ich möchte ignorieren "exit $?" innerhalb von second.sh .. ist ohne edit second.sh möglich?
Benutzer3589887

Antworten:

13

Was Sie hier tun, ist das Einschließen second.shund third.shals Unterskripte, die im selben Prozess ausgeführt werden, der in der Shell-Programmierung als "Sourcing" bezeichnet wird. . ./second.shist im Grunde gleichbedeutend mit dem Einfügen des Textes von second.shan diesem Punkt. Der exitBefehl beendet den Prozess. Es spielt keine Rolle, ob Sie ihn im ursprünglichen Skript oder in einem Quellenskript aufrufen.

Wenn alles , was Sie tun möchten , ist die Befehle läuft in second.shund third.shund sie nicht dem Zugriff auf oder ändern Variablen und Funktionen von dem Original - Skript benötigen, diese Skripte als Kindprozesse nennen.

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

Wenn Sie die anderen Skripte benötigen, um über das ursprüngliche Skript auf Variablen und Funktionen zuzugreifen, diese jedoch nicht zu ändern, rufen Sie diese Skripte in Subshells auf. Unterschalen sind separate Prozesse, daher werden exitnur sie beendet.

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

Wenn Sie Variablen oder Funktionen verwenden müssen, die im second.shund third.shim übergeordneten Skript definiert sind, müssen Sie diese weiterhin beschaffen.

Das returneingebaute Skript beendet nur das Sourcing-Skript und nicht den gesamten Prozess. Dies ist einer der wenigen Unterschiede zwischen dem Einfügen eines anderen Skripts in den .Befehl und dem Einfügen seines Texts in das übergeordnete Skript. Wenn die sourced Skripte nur ruft exitan dem Toplevel, wie nach innen Funktionen gegenüber , dann können Sie ändern exitin return. Sie können dies tun, ohne das Skript mithilfe eines Alias ​​zu ändern.

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

Wenn exites auch innerhalb von Funktionen genannt wird, glaube ich nicht, dass es einen nicht umständlichen Weg gibt. Eine umständliche Möglichkeit besteht darin, eine Ausgangsfalle einzurichten und Ihren Code dort abzulegen.

#!/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 - hör auf böse zu sein'
quelle
Aus diesem Grund habe ich die Verwendung von '.' um Dateien in ein Skript zu quellen und stattdessen ausschließlich 'source' zu verwenden. IMO, die als "Best Practice" angesehen werden sollte, da sie viel klarer macht, was Ihr Code tut.
Mark E. Hamilton
6

Anstatt die zweite und dritte Shell zu beziehen, führen Sie sie einfach wie jeden anderen Befehl aus. Der Exit-Code kann gespeichert und bei Bedarf verwendet werden:

#! /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
quelle
STATUS1=$?fängt das Ergebnis eines zuvor ausgegebenen Echo-Befehls ab, der unabhängig vom Ergebnis von ist ./second.sh.
Cromax
@Cromax du hast vollkommen recht. Antwort wurde bearbeitet.
Dale Anderson
0

Versuchen Sie es so (zuerst .beim Anruf entfernen 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 $?

Dies liegt daran, dass .es sich um einen Shortcode handelt, für sourceden das zweite Skript als Teil des ersten Skripts aufgenommen wird.

Mojtaba Rezaeian
quelle