Chiama uno script per un altro script, ma non uscire dal genitore se il bambino chiama 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 $?

Se second.shrileva un errore ed esce con lo stato -9, first.shesce sempre. Come posso evitare di uscire dalla prima shell se la shell figlio esce?

Non riesco a modificare second.sh.


Qui stai usando il .comando, che genera un altro file nella shell corrente. Non ci sono shell secondarie o subshell coinvolte. Intendevi eseguire second.sh e third.shinvece di acquistarli?
Celada,

si .. devo scrivere eseguire invece di. ./? voglio ignorare "exit $?" all'interno di second.sh .. è possibile senza modificare second.sh?
user3589887

Risposte:


13

Quello che stai facendo qui è includere second.she third.shcome script secondari in esecuzione nello stesso processo, che viene chiamato "sourcing" nella programmazione della shell. . ./second.shè sostanzialmente equivalente a includere il testo di second.sha quel punto. Il exitcomando esce dal processo, non importa se lo chiami nello script originale o in uno script di provenienza.

Se tutto ciò che vuoi fare è eseguire i comandi second.she third.shnon è necessario che accedano o modifichino variabili e funzioni dallo script originale, chiama questi script come processi figlio.

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

Se hai bisogno degli altri script per accedere a variabili e funzioni dallo script originale, ma non modificarli, chiama questi script in subshells. I sotto-shell sono processi separati, quindi ne exitescono solo.

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

Se è necessario utilizzare variabili o funzioni definite in second.she third.shnello script principale, è necessario continuare a reperirle.

Il returnbuiltin esce solo dallo script di provenienza e non dall'intero processo - questa è una delle poche differenze tra l'inclusione di un altro script con il .comando e l'inclusione del suo testo nello script principale. Se gli script di origine chiamano solo exital livello superiore, al contrario delle funzioni interne, è possibile cambiare exitin return. Puoi farlo senza modificare lo script usando 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"

Se exitviene anche chiamato funzioni interne, non penso che ci sia un modo non ingombrante. Un modo ingombrante è impostare una trappola di uscita e inserire il codice lì.

#!/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

È per questo motivo che ho smesso di usare '.' per generare i file in uno script e provare invece a utilizzare esclusivamente "source". IMO che dovrebbe essere considerata una "best practice" bash, poiché rende molto più chiaro ciò che sta facendo il tuo codice.
Mark E. Hamilton,

6

Invece di approvvigionare la seconda e la terza shell, eseguitele come fareste con qualsiasi altro comando. Il codice di uscita può essere memorizzato e utilizzato se necessario, in questo modo:

#! /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...

STATUS1=$?prenderà il risultato del comando echo precedentemente emesso, che è indipendente dal risultato di ./second.sh.
Cromax,

@Cromax hai perfettamente ragione. La risposta è stata modificata
Dale Anderson,

0

Provalo in questo modo (rimuovi prima la .chiamata 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 $?

Questo perché .è uno shortcode per il sourcequale viene incluso il secondo script come parte del primo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.