2012-10-11 8 views
7

Znalazłem dla mnie dziwne zachowanie, którego nie potrafię wyjaśnić. Poniższy kod jest praca OK:Wartość zwracana z podpowłoki i wyjście do zmiennych lokalnych

function prepare-archive { 
blah-blah-blah... 
_SPEC_FILE=$(check-spec-file "$_GIT_DIR/packaging/") 
exit $? 
blah-blah-blah... 
} 

Oznacza uzyskać wartość, która spodziewam:

bash -x ./this-script.sh: 
++ exit 1 
+ _SPEC_FILE='/home/likern/Print/Oleg/print-service/packaging/print-service.spec 
/home/likern/Print/Oleg/print-service/packaging/print-service2.spec' 
+ exit 1 

Jak tylko dodam local definicję zmiennej:

local _SPEC_FILE=$(check-spec-file "$_GIT_DIR/packaging/") 

otrzymuję następujący :

bash -x ./this-script.sh: 
++ exit 1 
+ local '_SPEC_FILE=/home/likern/Print/Oleg/print-service/packaging/print-service.spec 
/home/likern/Print/Oleg/print-service/packaging/print-service2.spec' 
+ exit 0 
$:~/MyScripts$ echo $? 
0 

Pytanie: Dlaczego? Co się stało? Czy mogę przechwytywać dane wyjściowe z podpowłoki do zmiennej local i niezawodnie sprawdzić wartość zwracaną przez powłokę?

P.S.: prepare-archive jest wywoływane w głównym skrypcie powłoki. Pierwsza exit jest funkcją exit z check-spec-file, druga z funkcji prepare-archive - ta sama funkcja jest wykonywana z głównego skryptu powłoki. Zwracam wartość z check-spec-file przez exit 1, następnie przekazuję tę wartość do exit $?. Tak więc oczekuję, że powinny być takie same.

+0

W jakim kontekście wywoływane jest 'prepare-archive'? '++ exit 1' nie pasuje do żadnego z pokazywanych przez ciebie kodów. – chepner

Odpowiedz

4

z podręcznika bash Shell Builtin Commands sekcja:

local: 
    [...]The return status is zero unless local is used outside a function, an invalid name is supplied, or name is a readonly variable. 

Nadzieja to pomaga =)

+0

Czy to oznacza, że ​​definicja zmiennej nie ma statusu powrotu, gdy jest używana bez 'local'? Czemu? Czy znasz jakieś obejścia - ponieważ nie chcę produkować zbytecznych zmiennych globalnych. –

+0

Nie jestem świadomy żadnych obejść, które nie wymagają utworzenia zmiennej globalnej lub użycia plików, sorry = (. Chciałbym zrobić "lokalny TMPFILE = $ (mktemp); check-spec-file> $ TMPFILE ; błąd lokalny = $ ?, lokalny _SPEC_FILE = $ (cat $ TMPFILE); rm $ TMPFILE' –

+1

@Mephi_stofel - aby obejść go, możesz podzielić deklarację i inicjalizację, np. najpierw: 'local my_var' i niż: 'my_var = $ (my_function)' .Inicjalizacja bezpiecznie odwoła się do zmiennej lokalnej, bez zanieczyszczania zasięgu globalnego –

12

Aby uchwycić stan wyjścia podpowłoki, w zadeklarować zmienną jako lokalny przed przypisaniem, na przykład, poniższy skrypt

#!/bin/sh 

local_test() 
{ 
    local local_var 
    local_var=$(echo "hello from subshell"; exit 1) 
    echo "subshell exited with $?" 
    echo "local_var=$local_var" 
} 

echo "before invocation local_var=$local_var in global scope" 
local_test 
echo "after invocation local_var=$local_var in global scope" 

daje następujący wynik

before invocation local_var= in global scope 
subshell exited with 1 
local_var=hello from subshell 
after invocation local_var= in global scope 
+0

Umysł wyjaśniający, co się tutaj dzieje? Twoja odpowiedź naprawiła mój problem, ale nadal nie rozumiem, jak i dlaczego tak się dzieje –

+1

@IhorKaharlichenko Jeśli zmienna jest przypisana w deklaracji z 'local', stan wyjścia sub-powłoki jest" zamaskowany "/overriden przy wyjściu s tatus z wbudowanego polecenia 'local'. Deklarowanie zmiennej lokalnej przed przypisaniem jest również bardziej przenośne (niektóre powłoki nie obsługują inicjalizacji za pomocą 'local'). – vilpan