Jaka jest różnica między poleceniem
$ env FOO=bar baz
i
$ FOO=bar baz
Jaki efekt envma?
Jaka jest różnica między poleceniem
$ env FOO=bar baz
i
$ FOO=bar baz
Jaki efekt envma?
Odpowiedzi:
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.
FOO=bar exec baz, więc nie potrzebujesz envostatniego punktu.
execcoś robisz , czy korzysta z twojego obecnego środowiska?
sudo FOO=bar bazmożna przekazywać zmienne środowiskowe bez potrzeby env.
FOO=barw skrypcie. Jeśli FOOnie 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 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
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ń 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:
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 -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.