Gdzie „eksport var = wartość” jest niedostępny?


31

Podniosłem - prawdopodobnie na Usenecie w połowie lat 90. (!) - ten konstrukt

export var=value

jest baszizmem, a tym przenośnym wyrażeniem jest

var=value
export var

Opowiadam się za tym od lat, ale ostatnio ktoś mnie o to rzucił i naprawdę nie mogę znaleźć żadnej dokumentacji na poparcie tego, co kiedyś było moją solidną wiarą.

Googling "export: command not found"nie wydaje się przywoływać przypadków, w których ktoś rzeczywiście miał ten problem, więc nawet jeśli jest to autentyczne, myślę, że nie jest to zbyt powszechne.

(Trafienia, które dostaję, wydają się być nowicjuszami, którzy kopiują / wklejają interpunkcję i skończyli z 'export: command not foundniektórymi lub starają się exportz nimi korzystać sudo; i nowi cshużytkownicy próbują używać składni powłoki Bourne'a.)

Z pewnością mogę powiedzieć, że działa na OS X i na różnych dystrybucjach Linuksa, w tym tych, gdzie shjest dash.

sh$ export var=value
sh$ echo "$var"
value
sh$ sh -c 'echo "$var"'  # see that it really is exported
value

Czy w dzisiejszym świecie można bezpiecznie stwierdzić, że export var=valuejest bezpieczny w użyciu?

Chciałbym zrozumieć, jakie są konsekwencje. Jeśli nie jest przenośny na v7 „Bourne classic”, to niewiele więcej niż ciekawostki. Jeśli istnieją systemy produkcyjne, w których powłoka naprawdę nie radzi sobie z tą składnią, warto by to wiedzieć.


2
dzięki W końcu zrozumiałem, dlaczego tak często widzę rzecz, która moim zdaniem była bezużyteczna: var = wartość; eksport var
Thorsten Staerk

2
Wciąż kręci się kilka pudeł Solaris, a te są zwykle oszczędne w swoich standardowych narzędziach; na drugim końcu spektrum, czy nie busyboxma własnej minimalnej powłoki? (Nie jestem w stanie ani spróbować w tej chwili.)
Ulrich Schwarz

Dzięki Ulrichowi Solaris może być sprawcą, dlaczego ta długa składnia wciąż istnieje.
Thorsten Staerk

Odpowiedzi:


20
export foo=bar

nie był obsługiwany przez powłokę Bourne'a (stara powłoka z lat 70., z której pochodzą nowoczesne shimplementacje, takie jak ash / bash / ksh / yash / zsh). Zostało to wprowadzone przez ksh.

W powłoce Bourne'a zrobiłbyś:

foo=bar export foo

lub:

foo=bar; export foo

lub z set -k:

export foo foo=bar

Teraz zachowanie:

export foo=bar

różni się w zależności od powłoki.

Problem polega na tym, że przypisania i proste argumenty poleceń są analizowane i interpretowane w różny sposób.

The foo=barPowyżej interpretować niektóre powłoki jako argument polecenia i innych jako przypisanie (czasami).

Na przykład,

a='b c'
export d=$a

jest interpretowany jako:

'export' 'd=b' 'c'

z niektórymi powłokami ( ash, starszymi wersjami zsh(w emulacji sh) yash) i:

'export' 'd=b c'

w pozostałych ( bash,ksh ).

Podczas

export \d=$a

lub

var=d
export $var=$a

będzie interpretowany tak samo we wszystkich powłokach (jak 'export' 'd=b' 'c' ), ponieważ ten ukośnik odwrotny lub znak dolara zatrzymuje te powłoki, które go obsługują, aby uznać te argumenty za przypisania.

Gdyby exportcytowany był sam lub wynik jakiegoś rozszerzenia (nawet częściowo), w zależności od powłoki, przestałby również otrzymywać specjalne traktowanie.

Więcej informacji na ten temat znajduje się w części „ Czy do przypisywania zmiennych lokalnych potrzebne są oferty? ”.

Jednak składnia Bourne'a:

d=$a; export d

jest interpretowany tak samo przez wszystkie powłoki bez dwuznaczności ( d=$a export ddziałałby również w powłokach Bourne'a i powłokach zgodnych z POSIX, ale nie w najnowszych wersjach, zshchyba że w shemulacji).

Może być znacznie gorzej. Zobacz na przykład niedawną dyskusję na temat tego,bash kiedy tablice są zaangażowane.

(IMO wprowadzanie tej funkcji było błędem ).


Byłem zaskoczony, że średnik nie jest wymagany foo=bar export foo, ponieważ zawsze go tam widziałem. Wiem, że eksport jest wbudowany, ale dlaczego foo=bar; foo=baz export foo; echo $foozachowuje się inaczej niż foo=bar; foo=baz /bin/cat /dev/null; echo $foo?
jrw32982 obsługuje Monikę

3
@ jrw32982, ponieważ jest to wbudowany. Nadal się, że w nowoczesnych powłok POSIX ale tylko do szczególnych poleceń wbudowanych , które exportjest.
Stéphane Chazelas,

Chociaż dyskutuje declare, nie export, polecam każdemu, kto dba o bezpieczeństwo, przeczytanie dyskusji pod linkiem, który StéphaneChazelas podał bash.bugs .
John1024,

Świetna odpowiedź! Ale zajęło dużo czasu, aby się d=$a export dzinterpretować tak samo przez wszystkie muszle bez dwuznaczności ;-)
conny

@conny, d=$a export djuż nie działa zsh, więc zaktualizowałem odpowiedź. Zobacz edycję.
Stéphane Chazelas

28

To nie jest bashizm, ale składnia zgodna z POSIX. Zaczęło się od kshizmu już dawno temu, a później zostało przyjęte przez prawie wszystkie powłoki oparte na składni Bourne'a. Jedynym notorycznym wyjątkiem jest /bin/shSolaris 10 i starszy, który trzyma się starszej składni powłoki Bourne'a. Mamy nadzieję, że Solaris 11 używa powłoki zgodnej z POSIX jako /bin/sh.

Nawiasem mówiąc, exportbyło już wbudowanym poleceniem w starszej powłoce Bourne'a, więc google szukanie export: command not foundbyło mylące.

Oto starsze zachowanie powłoki Bourne'a w exportpołączeniu z afektacją:

$ export var=22
var=22: is not an identifier

Dla osób nostalgicznych dostępny jest kod źródłowy tej oryginalnej powłoki Bourne'a, który można skompilować dla większości dystrybucji Uniksa i Linuksa.


Wielkie dzięki za historyczny wgląd i prawidłowy komunikat o błędzie dla Google! Oczywiste z perspektywy czasu, rumieniec ...
tripleee

4
To nie jest kod źródłowy oryginalnej powłoki Bourne'a, to zmodyfikowany sh OpenSolaris. Jest to skorupa Bourne'a, ale po dziesięcioleciach ewolucji. Oryginalną powłokę Bourne'a dostarczoną z Unixem V7 można znaleźć w Unix Heritage Society
Stéphane Chazelas

1
@ StéphaneChazelas Ściśle mówiąc, masz jak zwykle rację. Zauważ jednak, że nie napisałem „oryginalnej powłoki Bourne'a”, ale „tej oryginalnej powłoki Bourne'a”, ponieważ miałem na myśli powłokę używaną przez Solaris 10 i jej kod źródłowy, który można skompilować na nowoczesnych platformach. Zauważ też, że powłoka Bourne'a miała kilka funkcji dodanych między 1977 a 1989 rokiem, ale potem zasadniczo przestała ewoluować (poza przenoszeniem / adaptacją do nowszych platform i poprawek błędów) w ciągu ostatnich 25 lat.
jlliagre
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.