Stycznie zauważ również, że export name=valuenie jest przenośny. W zależności od tego, czego dokładnie chcesz, wypróbuj name=value; export nameprzenośne rozwiązanie.
tripleee
Odpowiedzi:
1054
export udostępnia zmienną podprocesom.
To jest,
export name=value
oznacza, że nazwa zmiennej jest dostępna dla każdego procesu uruchamianego z tego procesu powłoki. Jeśli chcesz, aby proces korzystał z tej zmiennej, użyj exporti uruchom proces z tej powłoki.
name=value
oznacza, że zmienny zakres jest ograniczony do powłoki i nie jest dostępny dla żadnego innego procesu. Użyłbyś tego do (powiedzmy) zmiennych pętli, zmiennych tymczasowych itp.
Należy zauważyć, że eksportowanie zmiennej nie udostępnia jej procesom nadrzędnym. Oznacza to, że określenie i eksportowanie zmiennej w odrodzonym procesie nie powoduje, że jest ona dostępna w procesie, który ją uruchomił.
W szczególności eksport udostępnia zmienną procesom potomnym za pośrednictwem środowiska.
Beano
15
Dodałbym również, że jeśli eksport znajduje się w pliku, który „źródło” (np.. Filename), to eksportuje go również do środowiska pracy.
rogerdpack,
6
@rogerdpack nie możesz tego zrobić bez eksportu? cat> bla \ na = hi \ n. bla; echo $ a; wypisuje dla mnie „cześć”.
David Winiecki
2
Fajnie, że działa nawet bez eksportu. Sądzę więc, że podczas pobierania pliku, jeśli użyjesz eksportu, zostanie on odzwierciedlony w procesach potomnych, jeśli nie, wpłynie to tylko na lokalne środowisko bash ...
rogerdpack
19
Jest w tym jeden przypadek; name=value commandma sprawić, że zmienna dostępna w sub-process command.
Jeszcze jeden przykład tegoal$ foobar="Whatever" bash
Alun,
70
Inni odpowiedzieli, że eksport udostępnia zmienną do podpowłoki, i jest to poprawne, ale tylko efekt uboczny. Kiedy eksportujesz zmienną, umieszcza ją w środowisku bieżącej powłoki (tj. Wywołania powłoki putenv(3)lub setenv(3)).
Środowisko procesu jest dziedziczone w całym exec, dzięki czemu zmienna jest widoczna w podpowłokach.
Edycja (z perspektywą 5 lat): to głupia odpowiedź. Celem „eksportu” jest sprawienie, aby zmienne „znajdowały się w środowisku później wykonywanych poleceń”, niezależnie od tego, czy są to podpowłoki, czy podprocesy. Naiwną implementacją byłoby po prostu umieszczenie zmiennej w środowisku powłoki, ale uniemożliwiłoby to implementację export -p.
Pamiętaj, że nie jest to do końca prawda. W bash, eksport rzeczywiście dodaje zmienną do środowiska bieżącej powłoki, ale tak nie jest dash. Wydaje mi się, że dodanie zmiennej do środowiska bieżącej powłoki jest najprostszym sposobem na zaimplementowanie semantyki export, ale takie zachowanie nie jest wymagane.
William Pursell,
7
Nie jestem pewien, co dashma z tym wspólnego. Oryginalny plakat pytał konkretnie o bash.
Rozgwiazda
14
Pytanie jest oznaczone, bashale dotyczy w równym stopniu każdego wariantu bourne-shell. Bycie zbyt konkretnym i udzielanie odpowiedzi, które dotyczą tylko, bashjest wielkim złem.
William Pursell,
12
bashjest jQuery powłoki.
Potherca
2
export makes the variable available to subshells, and that is correctJest to bardzo mylące użycie terminologii. Podkładki nie muszą exportdziedziczyć zmiennych. Podprocesy tak.
Amit Naidu
62
Powiedziano, że nie jest konieczne eksportowanie bash podczas odradzania podpowłoki, podczas gdy inni mówili dokładnie odwrotnie. Ważne jest, aby zwrócić uwagę na różnicę pomiędzy podpowłok (te, które są tworzone przez (), ``, $()lub pętle) i podprocesów (procesy, które są wywoływane przez nazwę, na przykład dosłowna bashpojawiające się w skrypcie).
Powłoki podrzędne będą miały dostęp do wszystkich zmiennych nadrzędnych, niezależnie od ich wyeksportowanego stanu.
Sub procesy będą tylko zobaczyć eksportowanych zmiennych.
Wspólne w tych dwóch konstrukcjach jest to, że żadne z nich nie może przekazać zmiennych z powrotem do powłoki nadrzędnej.
Jest jeszcze jedno źródło nieporozumień: niektórzy uważają, że podprocesy „rozwidlone” to te, które nie widzą nieeksportowanych zmiennych. Zwykle po fork () następuje zaraz po exec () i dlatego wydaje się, że fork () jest rzeczą, której należy szukać, podczas gdy w rzeczywistości jest to exec (). Za pomocą polecenia można najpierw uruchamiać polecenia bez fork () exec, a procesy uruchomione tą metodą również nie będą miały dostępu do niewyportowanych zmiennych:
Zauważ, że tym razem nie widzimy parent:linii, ponieważ zastąpiliśmy powłokę nadrzędną execpoleceniem, więc nie ma już nic do wykonania tego polecenia.
Nigdy nie widziałem pętli, która sama w sobie stworzyła podpowłokę; OTOH działa potok (zawsze dla elementów innych niż ostatnie, czasami dla ostatnich, w zależności od powłoki, wersji i opcji). Backgrounding ( &) tworzy również podpowłokę.
dave_thompson_085
Co z tymi var=asdf bash -c 'echo $var'lub var=asdf exec bash -c 'echo $var'? Dane wyjściowe to asdf. Różnica ;jest istotna, jeśli zostanie umieszczona po definicji zmiennej. Jakie byłoby wyjaśnienie? Wygląda na to, że var(bez ;) względy odradzającego się podprocesu, ponieważ powłoka pochodzenia nie ma z tym nic wspólnego. echo $varnie drukuje nic, jeśli zostanie wykonane w drugiej linii. Ale jedna podszewka var=asdf bash -c 'echo $var'; echo $vardaje asdf\nasdf.
4xy
31
export NAME=value dla ustawień i zmiennych mających znaczenie dla podprocesu.
NAME=value dla zmiennych tymczasowych lub pętli prywatnych dla bieżącego procesu powłoki.
Bardziej szczegółowo, exportoznacza nazwę zmiennej w środowisku, która kopiuje się do podprocesów i ich podprocesów podczas tworzenia. Żadna nazwa ani wartość nie jest nigdy kopiowana z podprocesu.
Częstym błędem jest umieszczenie spacji wokół znaku równości:
$ export FOO ="bar"
bash: export:`=': not a valid identifier
BPodproces widzi tylko wyeksportowaną zmienną ( ):
$ A="Alice"; export B="Bob"; echo "echo A is \$A. B is \$B"| bash
A is . B is Bob
Zmiany w podprocesie nie zmieniają głównej powłoki:
$ export B="Bob"; echo 'B="Banana"'| bash; echo $B
Bob
Zmienne oznaczone do eksportu mają wartości kopiowane podczas tworzenia podprocesu:
$ export B="Bob"; echo '(sleep 30; echo "Subprocess 1 has B=$B")'| bash &[1]3306
$ B="Banana"; echo '(sleep 30; echo "Subprocess 2 has B=$B")'| bash
Subprocess1 has B=BobSubprocess2 has B=Banana[1]+Done echo '(sleep 30; echo "Subprocess 1 has B=$B")'| bash
Tylko wyeksportowane zmienne stają się częścią środowiska ( man environ):
Należy zauważyć, że można wyeksportować zmienną, a później zmienić wartość. Zmieniona wartość zmiennej będzie dostępna dla procesów potomnych. Po ustawieniu eksportu dla zmiennej musisz zrobić, export -n <var>aby usunąć właściwość.
Dzięki, to jest dokładnie ta informacja, której szukałem, ponieważ widziałem skrypt, który używał zmiennych środowiskowych, a następnie „ponownie eksportował” je z nową wartością i zastanawiałem się, czy jest to konieczne.
Mike Lippert
8
Jak być może już wiesz, UNIX pozwala procesom mieć zestaw zmiennych środowiskowych, które są parami klucz / wartość, przy czym zarówno klucz, jak i wartość są łańcuchami. System operacyjny jest odpowiedzialny za utrzymanie tych par osobno dla każdego procesu.
Program może uzyskać dostęp do swoich zmiennych środowiskowych za pośrednictwem tego interfejsu API systemu UNIX:
char *getenv(const char *name);
int setenv(const char *name, const char *value, int override);
int unsetenv(const char *name);
Procesy dziedziczą również zmienne środowiskowe po procesach nadrzędnych. System operacyjny jest odpowiedzialny za tworzenie kopii wszystkich „envarów” w momencie tworzenia procesu potomnego.
Bash , między innymi powłokami, może ustawiać zmienne środowiskowe na żądanie użytkownika. Po to exportistnieje.
exportto polecenie Bash, aby ustawić zmienną środowiskową dla Bash. Wszystkie zmienne ustawione za pomocą tego polecenia będą dziedziczone przez wszystkie procesy, które utworzy Bash.
Innym rodzajem zmiennej w Bash jest zmienna wewnętrzna. Ponieważ Bash to nie tylko interaktywna powłoka, to tak naprawdę interpreter skryptów, tak jak każdy inny interpreter (np. Python) jest w stanie zachować swój własny zestaw zmiennych. Należy wspomnieć, że Bash (w przeciwieństwie do Pythona) obsługuje tylko zmienne łańcuchowe.
Notacją do definiowania zmiennych Bash jest name=value. Te zmienne pozostają w Bash i nie mają nic wspólnego ze zmiennymi środowiskowymi przechowywanymi przez system operacyjny.
Warto również zauważyć, że zgodnie z podręcznikiem użytkownika Bash:
Środowisko dla dowolnej prostej komendy lub funkcji można tymczasowo rozszerzyć, poprzedzając je przypisaniami parametrów, jak opisano w Parametry powłoki . Te instrukcje przypisania wpływają tylko na środowisko widziane przez to polecenie.
Podsumowując:
exportsłuży do ustawienia zmiennej środowiskowej w systemie operacyjnym. Ta zmienna będzie dostępna dla wszystkich procesów potomnych utworzonych przez bieżący proces Bash.
Notacja zmiennej Bash (nazwa = wartość) służy do ustawiania zmiennych lokalnych dostępnych tylko dla bieżącego procesu bash
Zapis zmiennej Bash poprzedzający inną komendę tworzy zmienną środowiskową tylko dla zakresu tej komendy.
bash vars nie obsługują tylu typów jak Python, ale mają łańcuch, liczbę całkowitą i dwa rodzaje tablic („indeksowane” / tradycyjne i „asocjacyjne”, które są podobne do tablicy awk, skrótu perl lub dict Pythona). Inne muszle różnią się; tylko ciąg jest przenośny .
dave_thompson_085
7
Odpowiedź Zaakceptowany Oznacza to, ale chciałbym, aby wyraźne połączenie poleceń wbudowanych powłoki:
Jak już wspomniano, exportudostępni zmienną zarówno powłoce, jak i dzieciom. Jeśli nieexport jest używana, zmienna będzie dostępna tylko w powłoce i tylko wbudowane powłoki mogą uzyskać do niej dostęp.
To jest,
tango=3
env | grep tango # prints nothing, since env is a child processset| grep tango # prints tango=3 - "type set" shows `set` is a shell builtin
Dwóch twórców UNIX, Brian Kernighan i Rob Pike, wyjaśniają to w swojej książce „The UNIX Programming Environment”. Google dla tytułu i łatwo znajdziesz wersję pdf.
Odnoszą się one do zmiennych powłoki w sekcji 3.6 i skupiają się na użyciu exportpolecenia na końcu tej sekcji:
Jeśli chcesz, aby wartość zmiennej była dostępna w podpowłokach, należy użyć polecenia eksportu powłoki. (Możesz pomyśleć o tym, dlaczego nie można wyeksportować wartości zmiennej z podpowłoki do jej rodzica).
Domyślnie zmienne utworzone w skrypcie są dostępne tylko dla bieżącej powłoki; procesy potomne (podpowłoki) nie będą miały dostępu do wartości, które zostały ustawione lub zmodyfikowane. Zezwolenie procesom potomnym na wyświetlanie wartości wymaga użycia polecenia eksportowania.
Chociaż nie jest to wyraźnie wspomniane w dyskusji, NIE jest konieczne użycie eksportu podczas odradzania podpowłoki z wewnętrznej bash, ponieważ wszystkie zmienne są kopiowane do procesu potomnego.
export name=value
nie jest przenośny. W zależności od tego, czego dokładnie chcesz, wypróbujname=value; export name
przenośne rozwiązanie.Odpowiedzi:
export
udostępnia zmienną podprocesom.To jest,
oznacza, że nazwa zmiennej jest dostępna dla każdego procesu uruchamianego z tego procesu powłoki. Jeśli chcesz, aby proces korzystał z tej zmiennej, użyj
export
i uruchom proces z tej powłoki.oznacza, że zmienny zakres jest ograniczony do powłoki i nie jest dostępny dla żadnego innego procesu. Użyłbyś tego do (powiedzmy) zmiennych pętli, zmiennych tymczasowych itp.
Należy zauważyć, że eksportowanie zmiennej nie udostępnia jej procesom nadrzędnym. Oznacza to, że określenie i eksportowanie zmiennej w odrodzonym procesie nie powoduje, że jest ona dostępna w procesie, który ją uruchomił.
źródło
name=value command
ma sprawić, że zmienna dostępna w sub-processcommand
.Aby zilustrować, co mówią inne odpowiedzi:
źródło
al$ foobar="Whatever" bash
Inni odpowiedzieli, że eksport udostępnia zmienną do podpowłoki, i jest to poprawne, ale tylko efekt uboczny. Kiedy eksportujesz zmienną, umieszcza ją w środowisku bieżącej powłoki (tj. Wywołania powłoki
putenv(3)
lubsetenv(3)
).Środowisko procesu jest dziedziczone w całym exec, dzięki czemu zmienna jest widoczna w podpowłokach.
Edycja (z perspektywą 5 lat): to głupia odpowiedź. Celem „eksportu” jest sprawienie, aby zmienne „znajdowały się w środowisku później wykonywanych poleceń”, niezależnie od tego, czy są to podpowłoki, czy podprocesy. Naiwną implementacją byłoby po prostu umieszczenie zmiennej w środowisku powłoki, ale uniemożliwiłoby to implementację
export -p
.źródło
bash
, eksport rzeczywiście dodaje zmienną do środowiska bieżącej powłoki, ale tak nie jestdash
. Wydaje mi się, że dodanie zmiennej do środowiska bieżącej powłoki jest najprostszym sposobem na zaimplementowanie semantykiexport
, ale takie zachowanie nie jest wymagane.dash
ma z tym wspólnego. Oryginalny plakat pytał konkretnie obash
.bash
ale dotyczy w równym stopniu każdego wariantu bourne-shell. Bycie zbyt konkretnym i udzielanie odpowiedzi, które dotyczą tylko,bash
jest wielkim złem.bash
jest jQuery powłoki.export makes the variable available to subshells, and that is correct
Jest to bardzo mylące użycie terminologii. Podkładki nie musząexport
dziedziczyć zmiennych. Podprocesy tak.Powiedziano, że nie jest konieczne eksportowanie bash podczas odradzania podpowłoki, podczas gdy inni mówili dokładnie odwrotnie. Ważne jest, aby zwrócić uwagę na różnicę pomiędzy podpowłok (te, które są tworzone przez
()
,``
,$()
lub pętle) i podprocesów (procesy, które są wywoływane przez nazwę, na przykład dosłownabash
pojawiające się w skrypcie).Wspólne w tych dwóch konstrukcjach jest to, że żadne z nich nie może przekazać zmiennych z powrotem do powłoki nadrzędnej.
Jest jeszcze jedno źródło nieporozumień: niektórzy uważają, że podprocesy „rozwidlone” to te, które nie widzą nieeksportowanych zmiennych. Zwykle po fork () następuje zaraz po exec () i dlatego wydaje się, że fork () jest rzeczą, której należy szukać, podczas gdy w rzeczywistości jest to exec (). Za pomocą polecenia można najpierw uruchamiać polecenia bez fork ()
exec
, a procesy uruchomione tą metodą również nie będą miały dostępu do niewyportowanych zmiennych:Zauważ, że tym razem nie widzimy
parent:
linii, ponieważ zastąpiliśmy powłokę nadrzędnąexec
poleceniem, więc nie ma już nic do wykonania tego polecenia.źródło
&
) tworzy również podpowłokę.var=asdf bash -c 'echo $var'
lubvar=asdf exec bash -c 'echo $var'
? Dane wyjściowe toasdf
. Różnica;
jest istotna, jeśli zostanie umieszczona po definicji zmiennej. Jakie byłoby wyjaśnienie? Wygląda na to, żevar
(bez;
) względy odradzającego się podprocesu, ponieważ powłoka pochodzenia nie ma z tym nic wspólnego.echo $var
nie drukuje nic, jeśli zostanie wykonane w drugiej linii. Ale jedna podszewkavar=asdf bash -c 'echo $var'; echo $var
dajeasdf\nasdf
.export NAME=value
dla ustawień i zmiennych mających znaczenie dla podprocesu.NAME=value
dla zmiennych tymczasowych lub pętli prywatnych dla bieżącego procesu powłoki.Bardziej szczegółowo,
export
oznacza nazwę zmiennej w środowisku, która kopiuje się do podprocesów i ich podprocesów podczas tworzenia. Żadna nazwa ani wartość nie jest nigdy kopiowana z podprocesu.Częstym błędem jest umieszczenie spacji wokół znaku równości:
B
Podproces widzi tylko wyeksportowaną zmienną ( ):Zmiany w podprocesie nie zmieniają głównej powłoki:
Zmienne oznaczone do eksportu mają wartości kopiowane podczas tworzenia podprocesu:
Tylko wyeksportowane zmienne stają się częścią środowiska (
man environ
):Teraz powinno być tak jasne, jak letnie słońce! Dzięki Brain Agnew, Alexp i Williamowi Prusellowi.
źródło
export
udostępni zmienną wszystkim skorupom rozwidlonym z bieżącej powłoki.źródło
Należy zauważyć, że można wyeksportować zmienną, a później zmienić wartość. Zmieniona wartość zmiennej będzie dostępna dla procesów potomnych. Po ustawieniu eksportu dla zmiennej musisz zrobić,
export -n <var>
aby usunąć właściwość.źródło
Jak być może już wiesz, UNIX pozwala procesom mieć zestaw zmiennych środowiskowych, które są parami klucz / wartość, przy czym zarówno klucz, jak i wartość są łańcuchami. System operacyjny jest odpowiedzialny za utrzymanie tych par osobno dla każdego procesu.
Program może uzyskać dostęp do swoich zmiennych środowiskowych za pośrednictwem tego interfejsu API systemu UNIX:
char *getenv(const char *name);
int setenv(const char *name, const char *value, int override);
int unsetenv(const char *name);
Procesy dziedziczą również zmienne środowiskowe po procesach nadrzędnych. System operacyjny jest odpowiedzialny za tworzenie kopii wszystkich „envarów” w momencie tworzenia procesu potomnego.
Bash , między innymi powłokami, może ustawiać zmienne środowiskowe na żądanie użytkownika. Po to
export
istnieje.export
to polecenie Bash, aby ustawić zmienną środowiskową dla Bash. Wszystkie zmienne ustawione za pomocą tego polecenia będą dziedziczone przez wszystkie procesy, które utworzy Bash.Więcej o środowisku w Bash
Innym rodzajem zmiennej w Bash jest zmienna wewnętrzna. Ponieważ Bash to nie tylko interaktywna powłoka, to tak naprawdę interpreter skryptów, tak jak każdy inny interpreter (np. Python) jest w stanie zachować swój własny zestaw zmiennych. Należy wspomnieć, że Bash (w przeciwieństwie do Pythona) obsługuje tylko zmienne łańcuchowe.
Notacją do definiowania zmiennych Bash jest
name=value
. Te zmienne pozostają w Bash i nie mają nic wspólnego ze zmiennymi środowiskowymi przechowywanymi przez system operacyjny.Więcej na temat parametrów powłoki (w tym zmiennych)
Warto również zauważyć, że zgodnie z podręcznikiem użytkownika Bash:
Podsumowując:
export
służy do ustawienia zmiennej środowiskowej w systemie operacyjnym. Ta zmienna będzie dostępna dla wszystkich procesów potomnych utworzonych przez bieżący proces Bash.źródło
Odpowiedź Zaakceptowany Oznacza to, ale chciałbym, aby wyraźne połączenie poleceń wbudowanych powłoki:
Jak już wspomniano,
export
udostępni zmienną zarówno powłoce, jak i dzieciom. Jeśli nieexport
jest używana, zmienna będzie dostępna tylko w powłoce i tylko wbudowane powłoki mogą uzyskać do niej dostęp.To jest,
źródło
Oto kolejny przykład:
Tylko przy użyciu eksportu VARTEST wartość VARTEST jest dostępna w sudo bash -c '...'!
Dalsze przykłady patrz:
http://mywiki.wooledge.org/SubShell
bash-hackers.org/wiki/doku.php/scripting/processtree
źródło
Dwóch twórców UNIX, Brian Kernighan i Rob Pike, wyjaśniają to w swojej książce „The UNIX Programming Environment”. Google dla tytułu i łatwo znajdziesz wersję pdf.
Odnoszą się one do zmiennych powłoki w sekcji 3.6 i skupiają się na użyciu
export
polecenia na końcu tej sekcji:źródło
Aby pokazać różnicę między wyeksportowaną zmienną znajdującą się w środowisku (env) a nieeksportowaną zmienną nie znajdującą się w środowisku:
Jeśli to zrobię:
wtedy w polu env pojawia się tylko $ OURNAME. Zmienna $ MYNAME nie znajduje się w env.
ale zmienna $ MYNAME istnieje w powłoce
źródło
Domyślnie zmienne utworzone w skrypcie są dostępne tylko dla bieżącej powłoki; procesy potomne (podpowłoki) nie będą miały dostępu do wartości, które zostały ustawione lub zmodyfikowane. Zezwolenie procesom potomnym na wyświetlanie wartości wymaga użycia polecenia eksportowania.
źródło
Chociaż nie jest to wyraźnie wspomniane w dyskusji, NIE jest konieczne użycie eksportu podczas odradzania podpowłoki z wewnętrznej bash, ponieważ wszystkie zmienne są kopiowane do procesu potomnego.
źródło