Cosa significa `{{(uscita 1); uscita 1; }; } `significa?


28

Ho citato il frammento di codice successivo da config.statusgenerato da configure.

if test ! -f "$as_myself"; then
{ { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
{ (exit 1); exit 1; }; }
fi

Nello snippet di codice, cosa fa { (exit 1); exit 1; };? Qual è lo scopo di fare solo exitin una subshell?

Risposte:


33

L'esecuzione (exit 1);è il modo più semplice di innescare una ERRtrappola. Inoltre attiverà l'uscita immediata se set -eè attiva. (L'attivazione della condizione di errore richiede il fallimento di un comando; exitcon un valore di errore in una subshell si verifica un errore della subshell.)

exit 1; non farà nessuna di queste cose.

Quindi {(exit 1); exit 1;}può essere utilizzato per produrre prima la ERRtrap, che potrebbe fare qualcosa di utile per scopi di debug, quindi terminare lo script con un'indicazione di errore.

Ma non è quello che succede nei autoconffile. autoconfgli script si basano sulla EXITtrap per ripulire i file temporanei creati durante l'esecuzione. La maggior parte delle shell, incluso bashimposterà lo stato dal valore fornito nel exitcomando prima di chiamare la EXITtrap. Ciò potrebbe consentire alla EXITtrap di rilevare se è stata invocata da un errore o da una normale terminazione e inoltre consente di assicurarsi che lo stato di uscita sia impostato correttamente alla fine dell'operazione trap.

Tuttavia, a quanto pare alcune shell non cooperano. Ecco una citazione dal autoconfmanuale :

Alcuni script di shell, come quelli generati da autoconf, usano una trap per ripulire prima di uscire. Se l'ultimo comando della shell è uscito con stato diverso da zero, anche la trap esce con stato diverso da zero in modo che l'invocatore possa dire che si è verificato un errore.

Sfortunatamente, in alcune shell, come Solaris /bin/sh, una trap di uscita ignora l'argomento del comando exit. In queste shell, una trap non può determinare se è stata invocata dalla semplice uscita o dall'uscita 1. Invece di chiamare direttamente exit, utilizzare la AC_MSG_ERRORmacro con una soluzione alternativa per questo problema.

La soluzione alternativa è assicurarsi che $?abbia lo stato di uscita primaexit dell'esecuzione del comando, in modo che abbia sicuramente quel valore quando EXITviene eseguita la trap. E, in effetti, è la AC_MSG_ERRORmacro che inserisce quel codice curioso, completo di parentesi graffe ridondanti.


Perché non eseguire solo falseanziché (exit 1)?
Ruslan,

3
@Ruslan: due problemi. (1) Più importante: falsenon consente di impostare il codice di stato e non vi è alcuna garanzia su quale stato diverso da zero restituisce. (2) di falsesolito non è incorporato, quindi richiede un processo figlio; al contrario, la maggior parte delle conchiglie può evitare di generare un bambino da gestire (exit 1).
rici,

8

Per quanto posso vedere, non vi è alcuno scopo, non c'è nulla che possa essere raggiunto direttamente avviando una subshell e poi uscendo immediatamente.

Cose come questa sono molto probabilmente un effetto collaterale della generazione automatica di codice - in alcuni casi potrebbero esserci altri comandi eseguiti nella sottostruttura in cui exit 1ha senso. In definitiva, c'è una buona probabilità che il codice di generazione sia in qualche modo semplificato, consentendogli di inserire alcune istruzioni che non hanno alcuna funzione in alcuni casi e generare "codice pulito" ogni volta è più complesso. Quello o il codice che ha generato quanto sopra è appena scritto male :)

L'uso liberale {...}è un altro esempio di questo, la maggior parte di essi è ridondante, ma è più facile scrivere codice che li inserisca in ogni caso (forse in alcuni si desidera reindirizzare l'output / input del blocco) piuttosto che distinguere il quelli dove non sono necessari e li omettono.


Ha uno scopo. Vedi la risposta di @ rici.
Old Pro,

1

(exit 1)è un modo semplice, probabilmente il più semplice per ottenere un certo codice di uscita (nel caso speciale di 1 ci sono modi più semplici, ovviamente). Ma questo non è il motivo in questo caso poiché il codice di uscita non viene esaminato.

Lo scopo di inserire exituna subshell potrebbe essere quello di non uscire dallo script (sebbene usando exit per la generazione di un certo codice di uscita).

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.