Co oznacza `{{(wyjście 1); wyjście 1; }; } `znaczy?

28

Zacytowałem kolejny fragment kodu config.statuswygenerowany przez 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

Co robi fragment kodu { (exit 1); exit 1; };? Jaki jest cel robienia tylko exitw podpowłoce?

MS.Kim
źródło

Odpowiedzi:

33

Wykonywanie (exit 1);jest najprostszym sposobem na uruchomienie ERRpułapki. Spowoduje również natychmiastowe wyjście, jeśli set -ejest aktywne. (Wywołanie warunku błędu wymaga wykonania komendy do niepowodzenia; exitwartość błędu w podpowłoce powoduje awarię podpowłoki).

exit 1; nie zrobi żadnej z tych rzeczy.

Więc {(exit 1); exit 1;}może być stosowany do pierwszego produkować ERRpułapkę, co może zrobić coś pożytecznego dla celów debugowania, a następnie wypowiedzieć skrypt ze wskazaniem błędów.

Ale nie o to chodzi w autoconfplikach. autoconfskrypty polegają na EXITpułapce w celu czyszczenia plików tymczasowych utworzonych podczas uruchamiania. Większość powłok, w tym bashustawia status na podstawie wartości podanej w exitpoleceniu przed wywołaniem EXITpułapki. To może pozwolić EXITpułapce na wykrycie, czy została wywołana na podstawie błędu, czy normalnego zakończenia, a także pozwala upewnić się, że status wyjścia jest poprawnie ustawiony na końcu operacji pułapki.

Jednak najwyraźniej niektóre pociski nie współpracują. Oto cytat z autoconfinstrukcji :

Niektóre skrypty powłoki, takie jak te generowane przez autoconf, używają pułapki do czyszczenia przed wyjściem. Jeśli ostatnia komenda powłoki została zakończona z niezerowym statusem, pułapka kończy się również ze statusem niezerowym, aby wywołujący mógł stwierdzić, że wystąpił błąd.

Niestety, w niektórych powłokach, takich jak Solaris /bin/sh, pułapka wyjścia ignoruje argument polecenia wyjścia. W tych powłokach pułapka nie może ustalić, czy została wywołana zwykłym wyjściem, czy wyjściem 1. Zamiast wywoływać wyjście bezpośrednio, użyj AC_MSG_ERRORmakra, które ma obejście tego problemu.

Obejściem tego problemu jest upewnienie się, że $?ma status wyjścia przed wykonaniem exitpolecenia, aby na pewno miał tę wartość po wykonaniu EXITpułapki. I rzeczywiście, to AC_MSG_ERRORmakro wstawia ten ciekawy kod wraz z redundantnymi nawiasami klamrowymi.

rici
źródło
Dlaczego po prostu nie wykonać falsezamiast (exit 1)?
Ruslan
3
@ Ruslan: Dwa problemy. (1) Najważniejsze: falsenie pozwala ustawić kodu statusu i nie ma gwarancji, jaki zwróci niezerowy status. (2) falsezwykle nie jest wbudowany, więc wymaga procesu potomnego; w przeciwieństwie do większości pocisków można uniknąć odradzania się dziecka (exit 1).
rici
8

O ile mi wiadomo, nie ma w tym celu celu, nic nie można osiągnąć bezpośrednio, uruchamiając podpowłokę, a następnie natychmiast wychodząc.

Takie rzeczy są najprawdopodobniej efektem ubocznym automatycznego generowania kodu - w niektórych przypadkach mogą istnieć inne polecenia wykonywane w podpowłoce, jeśli ma exit 1to sens. Ostatecznie istnieje spora szansa, że ​​kod generowania jest w jakiś sposób uproszczony, pozwalając mu wstawiać niektóre instrukcje, które w niektórych przypadkach nie mają żadnej funkcji, i generowanie „czystego kodu” za każdym razem jest bardziej złożone. Albo to, albo kod, który wygenerował powyższe, jest po prostu źle napisany :)

Liberalne użycie {...}jest kolejnym przykładem tego, większość z nich jest redundantna, ale łatwiej jest napisać kod, który wstawia je w każdym przypadku (być może w niektórych chcesz przekierować wyjście / wejście bloku) niż rozróżniać te, w których nie są potrzebne i pomiń je.

Graeme
źródło
Ma cel. Zobacz odpowiedź @ rici.
Old Pro
1

(exit 1)to prosty, prawdopodobnie najprostszy sposób na uzyskanie określonego kodu wyjścia (w specjalnym przypadku 1 są oczywiście łatwiejsze sposoby). Ale nie jest to przyczyną w tym przypadku, ponieważ kod wyjścia nie jest badany.

Celem umieszczenia exitpodpowłoki może być niezakończenie skryptu (chociaż użycie wyjścia do wygenerowania określonego kodu wyjścia).

Hauke ​​Laging
źródło