Coś w rodzaju pytania pobocznego, ale jak nazywa się ta funkcja, kiedy ustawiasz zmienną środowiskową dla jednej takiej komendy? Zawsze trudno mi było znaleźć informacje na ten temat, ponieważ nie wiem, jak się nazywa.
@JohnCromartie Jest to opcjonalny składnik każdego polecenia powłoki, dlatego znajduje się w sekcji „Proste polecenia” większości podręczników powłoki. W przypadku POSIX byłoby to tutaj . glenn połączył już dla ciebie analogiczną sekcję z podręcznika bash.
jw013
Ustawienie zmiennej, która nie istnieje za pomocą przypisania, tworzy zmienną powłoki. Ustawienie go za pomocą ENV lub wyeksportowanie zmiennej wypycha zmienną do środowiska wykonawczego powłoki. Zmiana wartości istniejącej zmiennej zaktualizuje wartość środowiska wykonawczego, jeśli taka istnieje, w przeciwnym razie zmień ją w wewnętrznych zmiennych powłoki.
Johan
Odpowiedzi:
26
Są funkcjonalnie równoważne.
Główna różnica polega na tym, że wywołuje się env FOO=bar bazproces pośredni między powłoką i baz, jak w FOO=bar bazprzypadku powłoki, bezpośrednio wywołuje baz.
W związku z tym FOO=bar bazjest preferowane.
Jedyne sytuacje, env FOO=barw których się przyzwyczajam, to przekazywanie polecenia innym poleceniom.
Jako konkretny przykład, powiedzmy, że mam skrypt otoki, który wykonuje pewne modyfikacje środowiska, a następnie wywołuje execprzekazane mu polecenie, takie jak:
#!/bin/bash
FOO=bob
some stuff
exec "$@"
Jeśli wykonasz to jako myscript FOO=bar baz, execwygeneruje błąd, ponieważ exec FOO=bar bazjest nieprawidłowy.
Zamiast tego wywołujesz go jako myscript env FOO=bar bazwykonywany jako exec env FOO=bar bazi jest on całkowicie poprawny.
Możesz to zrobić FOO=bar exec baz, więc nie potrzebujesz envostatniego punktu.
Stéphane Chazelas
Kiedy execcoś robisz , czy korzysta z twojego obecnego środowiska?
glenn jackman
1
Ditto @StephaneChazelas, a także sudo FOO=bar bazmożna przekazywać zmienne środowiskowe bez potrzeby env.
Mike Miller
1
@StephaneChazelas, który działa tylko wtedy, gdy chcę umieścić FOO=barw skrypcie. Jeśli FOOnie zawsze bar, nie chcę go kodować na sztywno, a zamiast tego przekazać.
Patrick
@glennjackman tak, tak długo, jak zmienne są eksportowane lub przekazywane przed exec, np FOO=bar exec baz.
Patrick
14
W tym konkretnym przykładzie nie ma skutecznej różnicy, zakładając, że twoja powłoka jest powłoką kompatybilną z POSIX, i zakładając, że bazjest wykonywalny, a nie wbudowany w powłokę.
Jeśli twoja powłoka nie jest powłoką kompatybilną z POSIX, na przykład cshlub tcshskładnia
FOO=bar baz
nie działa i nie ma równoważnej składni powłoki. W przypadku tych powłok envpolecenie jest jedynym sposobem na zastąpienie lub wstrzyknięcie zmiennych środowiskowych dla pojedynczego polecenia.
Jeśli bazjest wbudowana powłoka, powiedzmy fcna przykład, to envnie da takich samych wyników, ponieważ envwykonuje nowy proces zamiast być uruchamianym bezpośrednio przez powłokę poleceń. Co więcej, nie ma fcpliku wykonywalnego, można go uruchomić tylko jako wbudowaną powłokę ze względu na sposób, w jaki współdziała ona ze środowiskiem powłoki, a więc nigdy nieenv będzie działać z takim wbudowanym .fc
Ponadto envoferuje -iopcję, która pozwala uruchomić polecenie w pustym środowisku z określonym zestawem zmiennych środowiskowych. envMoże być więc bardzo przydatny na przykład do uruchamiania procesów w środowiskach odkażonych
będąc funkcją powłoki (Bourne / POSIX), masz ograniczoną nazwę zmiennych środowiskowych, które przekazujesz cmd. Muszą być poprawnymi nazwami zmiennych powłoki i nie mogą być zmiennymi tylko do odczytu lub specjalnymi zmiennymi dla powłoki.
Na przykład nie można wykonać:
1=foo cmd
Lub
+++=bar cmd
bash nie pozwala ci na:
SHELLOPTS=xtrace cmd
Chociaż możesz to zrobić:
env 1=foo cmd
env +++=bar cmd
env '=baz' cmd
(nie że chcesz lub powinieneś to zrobić). Lub:
env SHELLOPTS=xtrace cmd
(Czasami muszę to zrobić).
Zauważ, envże nadal nie możesz przekazać łańcucha zmiennej środowiskowej, który nie zawiera =(nie, że też chciałbyś to zrobić).
Jednym z zastosowań envjest umożliwienie $PATHwyszukiwania plików wykonywalnych w liniach shebang (ponieważ bierze envpod uwagę $PATHprzy wyszukiwaniu plików wykonywalnych). Jest to przydatne, jeśli plik wykonywalny, który chcesz wywołać, może znajdować się w różnych miejscach na różnych komputerach. Na przykład,
#!/usr/bin/env perl
w pierwszym wierszu skryptu z zestawem bitów wykonywalnych uruchomi ten skrypt w Perlu bez względu na to, czy jest on zainstalowany /usr/bin/perlw/usr/local/bin/perl innym miejscu, o ile katalog znajduje się na ścieżce.
Oczywiście, wyszukiwanie ścieżki wiąże się z dodatkowym ryzykiem, ale ryzyko to nie jest większe niż w przypadku wyraźnego napisania perl yourscript.pl, co również wyszukuje perla na ścieżce wyszukiwania.
Innym razem, gdy envjest to naprawdę przydatne, jest to, że chcesz całkowicie kontrolować środowisko. Uruchamiam program serwera (Informix, na wypadek, gdybyś nie zgadł), którego środowiskiem chcę całkowicie kontrolować. Uruchamiam go za envpomocą skryptu, który ustawia kilka zmiennych do poprawnych wartości:
Ta -iopcja zapełnia istniejące środowisko. Kolejne VAR=valueopcje ustawiają zmienne środowiskowe, które chcę ustawić; nazwa programu jest w $ONINIT, a wszelkie argumenty wiersza poleceń są przekazywane dosłownie za pomocą "$@".
${IXH:+INFORMIXSQLHOSTS="$IXH"}Konstrukt przechodzi tylko INFORMIXSQLHOSTS="$IXH"do envJeśli $IXHustawiony jest niepusty wartości.
Odpowiedzi:
Są funkcjonalnie równoważne.
Główna różnica polega na tym, że wywołuje się
env FOO=bar baz
proces pośredni między powłoką ibaz
, jak wFOO=bar baz
przypadku powłoki, bezpośrednio wywołujebaz
.W związku z tym
FOO=bar baz
jest preferowane.Jedyne sytuacje,
env FOO=bar
w których się przyzwyczajam, to przekazywanie polecenia innym poleceniom.Jako konkretny przykład, powiedzmy, że mam skrypt otoki, który wykonuje pewne modyfikacje środowiska, a następnie wywołuje
exec
przekazane mu polecenie, takie jak:Jeśli wykonasz to jako
myscript FOO=bar baz
,exec
wygeneruje błąd, ponieważexec FOO=bar baz
jest nieprawidłowy.Zamiast tego wywołujesz go jako
myscript env FOO=bar baz
wykonywany jakoexec env FOO=bar baz
i jest on całkowicie poprawny.źródło
FOO=bar exec baz
, więc nie potrzebujeszenv
ostatniego punktu.exec
coś robisz , czy korzysta z twojego obecnego środowiska?sudo FOO=bar baz
można przekazywać zmienne środowiskowe bez potrzebyenv
.FOO=bar
w skrypcie. JeśliFOO
nie zawszebar
, nie chcę go kodować na sztywno, a zamiast tego przekazać.exec
, npFOO=bar exec baz
.W tym konkretnym przykładzie nie ma skutecznej różnicy, zakładając, że twoja powłoka jest powłoką kompatybilną z POSIX, i zakładając, że
baz
jest wykonywalny, a nie wbudowany w powłokę.Jeśli twoja powłoka nie jest powłoką kompatybilną z POSIX, na przykład
csh
lubtcsh
składnianie działa i nie ma równoważnej składni powłoki. W przypadku tych powłok
env
polecenie jest jedynym sposobem na zastąpienie lub wstrzyknięcie zmiennych środowiskowych dla pojedynczego polecenia.Jeśli
baz
jest wbudowana powłoka, powiedzmyfc
na przykład, toenv
nie da takich samych wyników, ponieważenv
wykonuje nowy proces zamiast być uruchamianym bezpośrednio przez powłokę poleceń. Co więcej, nie mafc
pliku wykonywalnego, można go uruchomić tylko jako wbudowaną powłokę ze względu na sposób, w jaki współdziała ona ze środowiskiem powłoki, a więc nigdy nieenv
będzie działać z takim wbudowanym .fc
Ponadto
env
oferuje-i
opcję, która pozwala uruchomić polecenie w pustym środowisku z określonym zestawem zmiennych środowiskowych.env
Może być więc bardzo przydatny na przykład do uruchamiania procesów w środowiskach odkażonychźródło
tcsh
, pisałem,(setenv FOO bar; baz)
aby uzyskać równoważną funkcję.Oprócz tego, co już zostało powiedziane
będąc funkcją powłoki (Bourne / POSIX), masz ograniczoną nazwę zmiennych środowiskowych, które przekazujesz
cmd
. Muszą być poprawnymi nazwami zmiennych powłoki i nie mogą być zmiennymi tylko do odczytu lub specjalnymi zmiennymi dla powłoki.Na przykład nie można wykonać:
Lub
bash
nie pozwala ci na:Chociaż możesz to zrobić:
(nie że chcesz lub powinieneś to zrobić). Lub:
(Czasami muszę to zrobić).
Zauważ,
env
że nadal nie możesz przekazać łańcucha zmiennej środowiskowej, który nie zawiera=
(nie, że też chciałbyś to zrobić).źródło
Jednym z zastosowań
env
jest umożliwienie$PATH
wyszukiwania plików wykonywalnych w liniach shebang (ponieważ bierzeenv
pod uwagę$PATH
przy wyszukiwaniu plików wykonywalnych). Jest to przydatne, jeśli plik wykonywalny, który chcesz wywołać, może znajdować się w różnych miejscach na różnych komputerach. Na przykład,w pierwszym wierszu skryptu z zestawem bitów wykonywalnych uruchomi ten skrypt w Perlu bez względu na to, czy jest on zainstalowany
/usr/bin/perl
w/usr/local/bin/perl
innym miejscu, o ile katalog znajduje się na ścieżce.Oczywiście, wyszukiwanie ścieżki wiąże się z dodatkowym ryzykiem, ale ryzyko to nie jest większe niż w przypadku wyraźnego napisania
perl yourscript.pl
, co również wyszukuje perla na ścieżce wyszukiwania.źródło
Innym razem, gdy
env
jest to naprawdę przydatne, jest to, że chcesz całkowicie kontrolować środowisko. Uruchamiam program serwera (Informix, na wypadek, gdybyś nie zgadł), którego środowiskiem chcę całkowicie kontrolować. Uruchamiam go zaenv
pomocą skryptu, który ustawia kilka zmiennych do poprawnych wartości:Ta
-i
opcja zapełnia istniejące środowisko. KolejneVAR=value
opcje ustawiają zmienne środowiskowe, które chcę ustawić; nazwa programu jest w$ONINIT
, a wszelkie argumenty wiersza poleceń są przekazywane dosłownie za pomocą"$@"
.${IXH:+INFORMIXSQLHOSTS="$IXH"}
Konstrukt przechodzi tylkoINFORMIXSQLHOSTS="$IXH"
doenv
Jeśli$IXH
ustawiony jest niepusty wartości.źródło