Cattura il codice di uscita del comando di uscita


10

Ho questo in uno script bash:

exit 3;

exit_code="$?"

if [[ "$exit_code" != "0" ]]; then
    echo -e "${r2g_magenta}Your r2g process is exiting with code $exit_code.${r2g_no_color}";
    exit "$exit_code";
fi

Sembra che uscirà subito dopo il comando exit, il che ha senso. Mi chiedevo c'è qualche semplice comando in grado di fornire un codice di uscita senza uscire subito?

Stavo per indovinare:

exec exit 3

ma dà un messaggio di errore: exec: exit: not found. Cosa posso fare? :)


1
Sì, exec exit 3non c'è bueno, ottengo"exec: exit: not found"

7
Non capisco la domanda. Perché non impostare exit_code=3ed eliminare del exit 3tutto la linea?
wjandrea,

@wjandrea è più una domanda concettuale che pratica

2
Non ha ancora senso per me. Perché dovrebbe esserci un codice di uscita se non si esce effettivamente?
Barmar il

1
@Barmar ogni processo ha un codice di uscita. La maggior parte delle persone che stanno cercando di rispondere alla domanda interpretano la domanda nel senso che "cosa posso sostituire" exit 3 "con nello script in modo da impostare la $?variabile ma non uscire da questo script"?
Icaro,

Risposte:


32

Se si dispone di uno script che esegue un programma e osserva lo stato di uscita del programma (con  $?) e si desidera testare quello script facendo qualcosa che causa $?l'impostazione di un valore noto (ad es.  3), Basta fare

(exit 3)

Le parentesi creano una sotto-shell. Quindi il exitcomando fa uscire quella sotto-shell con lo stato di uscita specificato.


Inoltre, ai fini del debug sarebbe altrettanto semplice impostare exit_code="3"per i test
Centimane,


12

exitè un bash incorporato, quindi non puoi exec. Per il manuale di bash :

Lo stato di uscita di Bash è lo stato di uscita dell'ultimo comando eseguito nello script. Se non viene eseguito alcun comando, lo stato di uscita è 0.

Mettendo tutto questo insieme, direi che la tua unica opzione è quella di memorizzare il tuo stato di uscita desiderato in una variabile e, exit $MY_EXIT_STATUSquando appropriato.


hmmm cosa ne pensi dell'idea di @ G-man?

2
Forse ho frainteso quello che stai cercando di realizzare. Se stai solo cercando di impostare $?(anche se non sono davvero sicuro del motivo per cui lo faresti), sembra una risposta solida. Se vuoi solo impostarlo su un valore non riuscito, falseè un'altra opzione.
solarshado,

10

È possibile scrivere una funzione che restituisca lo stato indicato come argomento o, 255se non specificato, uno. (Lo chiamo perché ret"restituisce" il suo valore.)

ret() { return "${1:-255}"; }

e utilizzare retal posto della chiamata a exit. Questo evita l'inefficienza della creazione della sotto-shell nella risposta attualmente accettata.

Alcune misure.

time bash -c 'for i in {1..10000} ; do (exit 3) ; done ; echo $?'

sulla mia macchina impiega circa 3,5 secondi.

 time bash -c 'ret(){ return $1 ; } ; for i in {1..10000} ; do ret 3 ; done ; echo $?'

sulla mia macchina impiega circa 0,051 secondi, 70 volte più veloce. L'inserimento della gestione predefinita lo lascia ancora 60 volte più veloce. Ovviamente il loop ha delle spese generali. Se cambio il corpo del loop in modo che sia solo :o truequindi il tempo viene dimezzato a 0,025, un ciclo completamente vuoto non è una sintassi non valida. L'aggiunta ;:al ciclo mostra che questo comando minimo richiede 0,007 secondi, quindi il sovraccarico del ciclo è di circa 0,018. Sottrarre questo sovraccarico dai due test mostra che la retsoluzione è oltre 100 volte più veloce.

Ovviamente questa è una misura sintetica, ma le cose si sommano. Se rendi tutto 100 volte più lento del necessario, allora finisci con i sistemi lenti. 0.0


2
@iBug Lo spazio extra non è necessario.
Icaro,

Un buon punto sull'inefficienza della creazione della sotto-shell. Ho letto che alcune shell potrebbero essere abbastanza intelligenti da ottimizzare il fork in casi come questo, ma quella bash non è una di queste.
G-Man dice "Ripristina Monica" il

3

Informazioni su exec exit 3... tenterebbe di eseguire un comando esterno chiamato exit, ma non ce n'è uno, quindi si ottiene l'errore. Deve essere un comando esterno invece di uno incorporato nella shell, poiché exec sostituisce completamente la shell. Il che significa anche che anche se avessi un comando esterno chiamato exit, exec exit 3non tornerebbe per continuare lo script della shell, poiché la shell non ci sarebbe più .


1
Immagino che tu possa fare exec bash -c "exit 3", ma al momento non riesco a pensare a nessun motivo per farlo al contrario di Just exit 3.
David Z,

1
@DavidZ, in ogni caso, exec'ing o just exit' ing fermerà la sceneggiatura, che non sembrava ciò che la domanda voleva.
ilkkachu,

3

Puoi farlo con Awk:

awk 'BEGIN{exit 9}'

O Sed:

sed Q9 /proc/stat

... o con una conchiglia:sh -c 'exit 9'
ilkkachu il

1
@ilkkachu se hai intenzione di farlo potresti anche fare la (exit 9)risposta accettata
Steven Penny,
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.