Jaka jest różnica między poleceniem
$ env FOO=bar baz
i
$ FOO=bar baz
Jaki efekt env
ma?
Jaka jest różnica między poleceniem
$ env FOO=bar baz
i
$ FOO=bar baz
Jaki efekt env
ma?
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ą i baz
, jak w FOO=bar baz
przypadku powłoki, bezpośrednio wywołuje baz
.
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:
#!/bin/bash
FOO=bob
some stuff
exec "$@"
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 jako exec env FOO=bar baz
i jest on całkowicie poprawny.
FOO=bar exec baz
, więc nie potrzebujesz env
ostatniego punktu.
exec
coś robisz , czy korzysta z twojego obecnego środowiska?
sudo FOO=bar baz
można przekazywać zmienne środowiskowe bez potrzeby env
.
FOO=bar
w skrypcie. Jeśli FOO
nie zawsze bar
, nie chcę go kodować na sztywno, a zamiast tego przekazać.
exec
, np FOO=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
lub tcsh
składnia
FOO=bar baz
nie 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, powiedzmy fc
na przykład, to env
nie da takich samych wyników, ponieważ env
wykonuje nowy proces zamiast być uruchamianym bezpośrednio przez powłokę poleceń. Co więcej, nie ma fc
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
env -i HOME=/tmp/homedir "PATH=`getconf PATH`" "TERM=$TERM" FOO=bar baz
tcsh
, pisałem, (setenv FOO bar; baz)
aby uzyskać równoważną funkcję.
Oprócz tego, co już zostało powiedziane
VAR=value cmd args > redirs
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ń env
jest umożliwienie $PATH
wyszukiwania plików wykonywalnych w liniach shebang (ponieważ bierze env
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,
#!/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/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.
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 za env
pomocą skryptu, który ustawia kilka zmiennych do poprawnych wartości:
env -i HOME="$IXD" \
INFORMIXDIR="$IXD" \
INFORMIXSERVER="$IXS" \
${IXC:+INFORMIXCONCSMCFG="$IXC"} \
${IXH:+INFORMIXSQLHOSTS="$IXH"} \
IFX_LISTEN_TIMEOUT=3 \
ONCONFIG="onconfig.$IXS" \
PATH="/bin:/usr/bin:$IXD/bin" \
SHELL=/bin/ksh \
TZ=UTC0 \
$ONINIT "$@"
Ta -i
opcja zapełnia istniejące środowisko. Kolejne VAR=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 tylko INFORMIXSQLHOSTS="$IXH"
do env
Jeśli $IXH
ustawiony jest niepusty wartości.