Odpowiedzi:
Środowisko nie jest tak magiczne, jak mogłoby się wydawać. Powłoka przechowuje ją w pamięci i przechodzi do execve()
wywołania systemowego. Proces potomny dziedziczy go jako wskaźnik tablicy o nazwie environ
. Z strony execve
podręcznika:
STRESZCZENIE
#include <unistd.h> int execve(const char *filename, char *const argv[], char *const envp[]);
argv
to tablica ciągów argumentów przekazanych do nowego programu.
Zgodnie z konwencją pierwszy z tych ciągów powinien zawierać nazwę pliku powiązaną z wykonywanym plikiem.envp
jest tablicą ciągów, zwykle o postaci klucz = wartość, które są przekazywane jako środowisko do nowego programu.
Strona environ(7)
oferuje również wgląd:
STRESZCZENIE
extern char **environ;
OPIS
Zmienna
environ
wskazuje na tablicę wskaźników na ciągi zwane „środowiskiem”. Ostatni wskaźnik w tej tablicy ma wartośćNULL
. (Ta zmienna musi zostać zadeklarowana w programie użytkownika, ale jest zadeklarowana w pliku nagłówkowym,<unistd.h>
jeśli pliki nagłówkowe pochodzą z libc4 lub libc5, a jeśli pochodzą z glibc i zdefiniowano _GNU_SOURCE.) Ta tablica ciągów jest dostępna dla proces wywołany przez exec (3), który rozpoczął proces.
Obie strony GNU są zgodne ze specyfikacją POSIX
exec*e
warianty, które jawnie przekazują env, zamiast domyślnie używać environ
zmiennej globalnej. v
„Wektor” oznacza i odnosi się do argumentów polecenia przekazywane jako matrycy (raczej niż „liście” (funkcja zmiennej długości)) execve
jest połączeniem systemu i wszystkie inne exec*
funkcje libc opakowania na nim.
Po prostu źle to zrobisz: SOME_NAME=value
tworzy zmienną powłoki (w większości powłok). export SOME_NAME=value
tworzy zmienną środowiskową. Na lepsze na gorsze, większość powłok Unix / Linux / * BSD używa identycznej składni w dostępie do zmiennych środowiskowych i zmiennych powłoki.
W pewnym szerszym znaczeniu „środowisko” to tylko informacja, która towarzyszy wykonywaniu programu. W programach C, można znaleźć identyfikator procesu z getpid()
połączenia w programie Shell należałoby użyć zmiennej dostępu: $$
. Identyfikator procesu jest tylko częścią środowiska programu. Uważam, że termin „środowisko” pochodzi z niektórych bardziej teoretycznych zagadnień informatycznych, takich jak modelowanie wykonania programu. Modele wykonania programu mają środowisko „, które zawiera powiązania między zmiennymi a ich wartościami”.
I ta ostatnia, silniejsza definicja jest tym, czym jest „środowisko” dla powłok Unix / Linux / * BSD: związek między nazwami („zmiennymi”) i ich wartościami. W przypadku większości powłok w stylu uniksowym wszystkie wartości są ciągami znaków, chociaż nie jest to tak ściśle prawdziwe, jak kiedyś. Ksh, Zsh i Bash mają teraz zmienne maszynowe. Nawet definicje funkcji powłoki mogą być eksportowane.
Użycie środowiska odrębnego od zmiennych zwykłej powłoki obejmuje fork/exec
metodę uruchomienia nowego procesu używanego przez wszystkie Uniksy. Kiedy jesteś export
parą nazwa / wartość, ta para nazwa / wartość będzie obecna w środowisku nowych plików wykonywalnych, uruchamianych przez powłokę za pomocą execve(2)
wywołania systemowego (zwykle po znaku fork(2)
, z wyjątkiem sytuacji, gdy exec
użyto polecenia powłoki).
Po an execve()
, main()
funkcja nowego pliku binarnego ma swoje argumenty wiersza poleceń, środowisko (przechowywane jako tablica wskaźników zakończonych znakiem NULL do var=value
łańcuchów, patrz environ(7)
strona man). Inny odziedziczony stan obejmuje ulimit
ustawienia, bieżący katalog roboczy i wszelkie otwarte deskryptory plików, dla których program execve()
wywołujący nie miał ustawionego FD_CLOEXEC. Bieżący stan tty (włączony echo, tryb raw itp.) Można również uznać za część stanu wykonania odziedziczonego przez nowo opracowany exec
proces.
Zobacz bash
opis środowiska wykonawczego w podręczniku dla prostych poleceń (innych niż funkcje wbudowane lub powłoki).
Środowisko uniksowe różni się od co najmniej niektórych innych systemów operacyjnych: „leksyki” VMS można zmienić w procesie potomnym, a zmiana ta była widoczna w obiekcie nadrzędnym. VMS cd
w procesie potomnym wpłynie na katalog roboczy rodzica. Przynajmniej w niektórych okolicznościach, a moja pamięć może mnie zawodzić.
Niektóre zmienne środowiskowe są dobrze znane $HOME
, $PATH
, $LD_LIBRARY_PATH
i innych. Niektóre są konwencjonalne dla danego systemu programowania, dzięki czemu powłoka nadrzędna może przekazywać do programu wiele informacji specjalnych, takich jak określony katalog tymczasowy lub identyfikator użytkownika i hasło, które się nie wyświetlają ps -ef
. Proste programy CGI dziedziczą wiele informacji z serwera WWW na przykład poprzez zmienne środowiskowe.
SOME_NAME=value command
ustawi zmienną środowiskową SOME_NAME dla tego wywołania polecenia. Mylące wydaje się, że nie ustawia zmiennej powłoki o tej samej nazwie.
SOME_NAME=value command
zachowujesz się wbrew oczekiwaniom, jest to, że jest to specjalna składnia oznaczająca „dodaj SOME_NAME do środowiska przekazanego do komendy, ale w żaden inny sposób nie zmieniaj zmiennych tej powłoki”.
fork()
ed, ale do otrzymania (kopie) zmiennych powłoki.
Zmienne środowiskowe w swojej najbardziej surowej formie to tylko zestaw par nazwa / wartość. Jak opisano w bash man page ( man 1 bash
) w sekcji ENVIRONMENT:
When a program is invoked it is given an array of strings called the
environment. This is a list of name-value pairs, of the form
name=value.
The shell provides several ways to manipulate the environment. On
invocation, the shell scans its own environment and creates a parameter
for each name found, automatically marking it for export to child pro-
cesses. Executed commands inherit the environment.
W praktyce pozwala zdefiniować zachowanie wspólne lub unikalne dla programów wywoływanych z obecnej powłoki. Na przykład podczas używania crontab
lub visudo
można zdefiniować EDITOR
zmienną środowiskową, aby zdefiniować inny edytor inny niż domyślnie używany przez system. To samo można powiedzieć o man
poleceniu, które patrzy na twoje PAGER
środowisko, aby dowiedzieć się, z jakiego programu stronicującego należy korzystać do wyświetlania wyników strony podręcznika.
Sporo poleceń unixowych odczytuje środowisko i zależnie od tego, co jest tam ustawione, zmienia ich wyjście / przetwarzanie / działanie w zależności od nich. Niektóre są udostępniane, niektóre są unikalne dla programu. Większość stron podręcznika zawiera informacje o tym, jak zmienna środowiskowa wpływa na opisywany program.
Inne praktyczne ilustracje dotyczą np. Systemów z kilkoma instalacjami Oracle na tej samej platformie. Przez ustawienie ORACLE_HOME
cały zestaw poleceń Oracle (wczytanych ze PATH
zmiennej środowiskowej) następnie pobiera ustawienia, definicje, mapowania i biblioteki z tego katalogu najwyższego poziomu. To samo dotyczy innych programów, takich jak Java z jego JAVA_HOME
zmienną środowiskową.
bash sam ma wiele zmiennych środowiskowych, które mogą zmienić zachowanie różnych rzeczy z historii ( HISTSIZE
, HISTFILE
itp), wielkość ekranu ( COLUMNS
), zakończenie zakładki ( FIGNORE
, GLOBIGNORE
) Ustawienia regionalne i kodowania znaków / dekodowania ( LANG
, LC_*
), szybka ( PS1
.. PS4
), oraz itd. (ponownie szukaj wiedzy na stronie podręcznika użytkownika bash).
Możesz także pisać skrypty / programy korzystające z własnych niestandardowych zmiennych środowiskowych (do przekazywania ustawień lub zmiany funkcjonalności).
„Zmienne środowiskowe” to zestaw dynamicznych nazwanych wartości, które mogą wpływać na zachowanie zachodzących procesów na komputerze.
Są częścią środowiska operacyjnego, w którym działa proces. Na przykład działający proces może zapytać o wartość zmiennej środowiskowej TEMP, aby znaleźć odpowiednią lokalizację do przechowywania plików tymczasowych, lub zmienną HOME lub USERPROFILE, aby znaleźć strukturę katalogów należącą do użytkownika uruchamiającego proces.
Więcej informacji tutaj → http://en.wikipedia.org/wiki/Environment_variable .
Wszystko, co chcesz wiedzieć o zmiennych środowiskowych ... ↑
Ta odpowiedź wymaga nieco doświadczenia w skryptowaniu powłoki i znajomości terminów zmienna, wartość, podstawianie zmiennych, monit, echo, jądro, powłoka, narzędzie, sesja i proces.
Zmienna (envar) to zestaw globalnych zdefiniowanych zmiennych, które może mieć wpływ na sposób, w jaki dana procesy będą zachowywać się w systemie operacyjnym komputera.
Zastępujemy envary literami$
ai wielkimi literami . Na przykład: $PS1
.
Możemy wydrukować envar w ten sposób:
echo $PS1
$PS1
przechowuje wartość monitu Unix. Powiedz, że jego natywnymi wartościami są \u
\w
$
.
\u
oznacza (obecnego) użytkownika,\w
oznacza katalog roboczy,$
jest obramowanie monitu.Tak więc, jeśli robimy: echo $PS1
widzimy wartości \u
, \w
plus znak dolara w końcu.
Moglibyśmy zmienić zachowanie Unixa w tym kontekście, jeśli zmienimy wartości tej envory. Na przykład:
PS1="\w >"
Teraz monit wygląda następująco (zakładając, że katalog roboczy nosi nazwę „John”):
John >
W ten sam sposób, w jaki moglibyśmy to zrobić PS1="Hello, I'm your prompt >"
, echo $PS1
przyniosą:
Hello, I'm your prompt >
W Bash 4.xx możemy wydrukować WSZYSTKIE envary w systemie za pomocą env
polecenia. Sugeruję wykonanie env
w terminalu i przyjrzenie się wynikowi.
Terminal sesji pozwala nam dostosować envary, które nadchodzą z Bash.
Powyższe zmiany są zwykle tymczasowe i oto dlaczego:
Każda sesja (która nie jest podsesją) jest unikalna, a kilka procesów może być uruchomionych jednoznacznie w tym samym czasie (każda z własnym zestawem envarów), ale zwykle istnieje dziedziczenie od sesji 0 do sesji 1 i wyższych.
Zmiany, które wprowadzamy w jednym procesie, są dla niego unikalne i przestaną obowiązywać, jeśli zamkniemy go bez zapisania go w jakiś sposób.
Istnieje kilka rodzajów sposobów przechowywania zmian envar, w zależności od wybranego zakresu. Oto różne zakresy (poziomy) takich zmian:
Unix składa się z 3 głównych warstw: jądra, powłoki i narzędzi. AFAIK każda powłoka ma własne envary, które są zbudowane głównie lub wyłącznie w powłoce.
Specyficzna lokalizacja, w której się globalnie zmienić te zazwyczaj /etc/profile
choć możemy również zrobić w .bashrc
oczywiście.
Możemy tworzyć nowe envary i oto jest sposób; od wersji Bash 4.xx nie ma natywnej enavar o nazwie MESSAGE
(jak powiedziano, envary są zwykle pisane wielkimi literami).
MESSAGE="Hello world!"
stworzy go dla nas, a teraz, jeśli napiszemy echo $MESSAGE
, otrzymamy hello world!
.
Jeśli wykonamy bash
w bieżącej sesji roboczej (okno), zaczniemy nową podsekcję bash i nie będziemy już działać w pierwotnym procesie, chyba że wykonamy exit
.
Uwaga: W systemach operacyjnych z emulatorem terminali (takich jak Ubuntu Desktop) podsekcja zwykle działa w tym samym oknie, ale nowa sesja w innym oknie nie jest podsesją istniejącej (jest to proces sąsiedni ) .
Uwaga: Nie używaj specjalnych znaków w wartościach envar, takich jak! albo nie zostaną uratowani.
Nadal możemy używać envara utworzonego w pierwszej sesji, również w drugiej, bez rejestrowania go w plikach conf na poziomie użytkownika lub globalnym (patrz następujące dane). Oto jak to zrobić:
Przejdź do oryginalnej sesji (w bieżącym oknie lub w innym) i wykonaj:
export MESSAGE
podczas eksportowania nie używaj $
znaku.
Jest teraz eksportowany do wszystkich podsesji. Jeśli wykonasz echo $MESSAGE
sesję podrzędną, niezależnie od tego, czy pochodzi ona od użytkownika, czy inna, zostanie ona wydrukowana.
Zauważ, że wewnętrzne zmienne Shell, takie jak PS1
nie powinny być eksportowane, ale jeśli chcesz je wyeksportować z dowolnego powodu i nie pojawiają się, nie wykonuj bash
później export
, ale raczej bash –norc
.
$PATH
to środowisko, które użytkownicy najczęściej zmieniają najbardziej.
Jeśli my echo $PATH
, zobaczymy ten strumień:
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
Wydrukowane wartości tego envaru są oddzielone dwukropkami (:) tam, ale oto potencjalnie wygodniejszy sposób (są to te same wartości):
/usr/local/bin
/usr/bin
/bin
/usr/local/games
/usr/games
Są to katalogi, których należy szukać, gdy uruchamiamy narzędzie.
Wykonując which echo
, uzyskamy lokalizację jego pliku - na przykład możemy zobaczyć, że istnieje /bin/echo
.
Na tej podstawie nie musimy wpisywać echa envar, aby wyświetlić wartości evnar. Możemy również wykonać:
/bin/echo $ENVAR
Envar będzie nadal wykonywany, na przykład:
/bin/echo $HOME
Daje nam
/home/User || /root
Tak jak:
echo $HOME
Daje nam
/home/User || /root
Uwaga: w $HOME
skrócie ~
.
W Bash 4.xx, kiedy używamy narzędzia bez pełnej ścieżki, system użyje wszystkich 6 wartości wymienionych powyżej $PATH
envar. Tak więc zacznie się /user/local/bin
i będzie śledził całą zawartość w poszukiwaniu echo
pliku wykonywalnego.
W takim przypadku zatrzyma się na /bin/echo
, w którym w tym przypadku znajduje się plik wykonywalny.
Dlatego głównym powodem, dla którego możemy dostosować $PATH
envar, jest instalowanie plików wykonywalnych, które nie mieszczą się w żadnej z jego wartości natywnych.
Po zainstalowaniu takich plików wykonywalnych powinniśmy odpowiednio ustawić ich $PATH
wartość, a następnie moglibyśmy z nimi pracować.
$PATH
:Możemy export $PATH
rozbić pod sesje (w tym rozszerzenia bash, takie jak WP-CLI dla WordPress lub Drush dla Drupal) w ten sposób:
export PATH="/home/John:$PATH"
Spowoduje to dodanie nowej wartości /home/John
do $PATH
, a następnie w prawo potem, to załącza żadnych wartości rodzimych do niego (z prawej po dwukropku), które są przechowywane zgodnie ze składnią $PATH
.
Taką stałą zmianę można wykonać w odpowiednim skrypcie, zwykle pod /etc/profile
i pod nazwą .bashrc
.
!
niedziałającej wartości zmiennej środowiskowej, która znajduje się tuż pod przykładem pokazującym, że działa, fałszywe pojęcie podsesji, dość dziwna rada co robić po wyeksportowaniu zmiennej powłoki i fałszywym pojęciu globalnych zmiennych środowiskowych.
warning about ! in an environment variable value not working that is right below an example showing it working
? Proszę przykład.
quite bizarre advice about what to do after exporting a shell variable
, co dokładnie masz na myśli?
false notion of global environment variables
, co dokładnie masz na myśli?
exec(3)
rodziny (tj. Ci, którzy nie pasują do exec * v) przechodzą ** environment pod przykryciem.