Llame a un script para otro script, pero no salga del padre si el hijo llama a 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.shdetecta un error y sale con el estado -9, first.shsiempre sale. ¿Cómo puedo evitar salir del primer shell si sale el shell secundario?

No puedo editar second.sh.

usuario3589887
fuente
Aquí está utilizando el .comando, que genera otro archivo en el shell actual. No hay un shell o subshell secundario involucrado. ¿Querías ejecutar second.sh y en third.shlugar de buscarlos?
Celada
sí .. debo escribir ejecutar en lugar de. ./? Quiero ignorar "salir $?" dentro de second.sh .. es posible sin editar second.sh?
user3589887

Respuestas:

13

Lo que está haciendo aquí es incluir second.shy third.shcomo sub-scripts que se ejecutan en el mismo proceso, que se denomina "abastecimiento" en la programación de shell. . ./second.shes básicamente equivalente a incluir el texto second.shen ese punto. El exitcomando sale del proceso, no importa si lo llama en el script original o en un script de origen.

Si todo lo que quiere hacer es ejecutar los comandos second.shy third.shy ellos no tienen que acceder o modificar las variables y funciones de la escritura original, llama a estos scripts en subprocesos.

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

Si necesita los otros scripts para acceder a las variables y funciones del script original, pero no modificarlos, llame a estos scripts en subcapas. Las subcapas son procesos separados, por lo que exitsolo sale de ellas.

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

Si necesita utilizar variables o funciones definidas en second.shy third.shen la secuencia de comandos principal, deberá seguir obteniendo fuentes.

El returnbuiltin sale solo del script de origen y no de todo el proceso; esa es una de las pocas diferencias entre incluir otro script con el .comando e incluir su texto en el script principal. Si las secuencias de comandos de origen solo llaman exital nivel superior, en oposición a las funciones internas, entonces puede cambiar exita return. Puede hacerlo sin modificar el script utilizando 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 exittambién se llama funciones internas, no creo que haya una manera no engorrosa. Una forma engorrosa es establecer una trampa de salida y poner su código allí.

#!/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- deja de ser malvado'
fuente
Es por esta razón que he dejado de usar '.' fuente de archivos en una secuencia de comandos, e intente utilizar exclusivamente 'fuente' en su lugar. OMI que debe considerarse una "mejor práctica" bash, ya que deja mucho más claro lo que está haciendo su código.
Mark E. Hamilton
6

En lugar de obtener el segundo y el tercer shell, simplemente ejecútelos como lo haría con cualquier otro comando. El código de salida se puede almacenar y usar si lo necesita, así:

#! /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
fuente
STATUS1=$?capturará el resultado del comando echo emitido anteriormente, que es independiente del resultado de ./second.sh.
Cromax
@Cromax tienes toda la razón. La respuesta ha sido editada.
Dale Anderson
0

Pruébelo de esta manera (elimine primero .al llamar 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 $?

Esto se debe a que .es un código corto para el sourceque se incluye el segundo script como parte del primero.

Mojtaba Rezaeian
fuente