В чем разница между командами
$ env FOO=bar baz
а также
$ FOO=bar baz
Какой эффект envимеет?
В чем разница между командами
$ env FOO=bar baz
а также
$ FOO=bar baz
Какой эффект envимеет?
Ответы:
Они функционально эквивалентны.
Основное различие заключается в том, что вы env FOO=bar bazвызываете промежуточный процесс между оболочкой и baz, как и в случае с FOO=bar bazоболочкой, напрямую baz.
Так что в этом отношении FOO=bar bazпредпочтительнее.
Единственные ситуации, в которых я нахожусь, env FOO=bar- это когда я должен передать команду другой команде.
В качестве конкретного примера, допустим, у меня есть скрипт-обертка, который выполняет некоторые модификации среды, а затем вызывает execпереданную ему команду, такую как:
#!/bin/bash
FOO=bob
some stuff
exec "$@"
Если вы выполните его как myscript FOO=bar baz, он execвыдаст ошибку как exec FOO=bar bazнедействительную.
Вместо этого вы называете его так, как оно myscript env FOO=bar bazвыполняется exec env FOO=bar baz, и является совершенно допустимым.
FOO=bar exec bazхотя, так что вам не нужно envв последнем пункте.
execчто-то используете, это использует ваше текущее окружение?
sudo FOO=bar bazможете передавать переменные окружения без необходимости env.
FOO=barв сценарий. Если FOOне всегда bar, я не хочу жестко его кодировать, а вместо этого передать.
exec, например FOO=bar exec baz.
В этом конкретном примере нет эффективной разницы, если предположить, что ваша оболочка является POSIX-совместимой оболочкой, и предполагается, bazчто это исполняемый файл, а не встроенная оболочка.
Если ваша оболочка не является POSIX-совместимой оболочкой, например, cshили tcsh, синтаксис
FOO=bar baz
не работает, и нет эквивалентного синтаксиса оболочки. Для этих оболочек envкоманда является единственным способом переопределить или внедрить переменные среды для одной команды.
Если bazэто встроенная оболочка, скажем, fcнапример, то envона не даст таких же результатов, потому что envвыполняет новый процесс вместо того, чтобы запускаться непосредственно командной оболочкой. Более того, fcисполняемого файла нет , его можно запускать только как встроенную оболочку из-за того, как он взаимодействует со средой оболочки и поэтому никогда неenv будет работать со встроенным подобным .fc
Кроме того, envпредлагается -iопция, позволяющая запустить команду в пустой среде только с указанным набором переменных среды. Так что envможет быть очень полезным для запуска процессов в санитарных средах, например
env -i HOME=/tmp/homedir "PATH=`getconf PATH`" "TERM=$TERM" FOO=bar baz
tcshя писал, (setenv FOO bar; baz)чтобы получить эквивалентную функцию.
В дополнение к тому, что уже было сказано
VAR=value cmd args > redirs
Будучи функцией оболочки (Bourne / POSIX), вы ограничены в именах переменных среды, которые вы передаете cmd. Они должны быть допустимыми именами переменных оболочки и не должны быть только для чтения или специальными переменными для оболочки.
Например, вы не можете сделать:
1=foo cmd
Или
+++=bar cmd
bash не позволяет вам делать:
SHELLOPTS=xtrace cmd
Пока вы можете сделать:
env 1=foo cmd
env +++=bar cmd
env '=baz' cmd
(не то, что вы хотите или должны хотеть сделать это). Или:
env SHELLOPTS=xtrace cmd
(Мне иногда нужно это делать).
Обратите внимание, что envвы по-прежнему не можете передать строку переменной среды, которая не содержит =(не то, что вы хотели бы сделать это либо).
Одним из применений envявляется возможность $PATHпоиска исполняемых файлов в строках shebang (потому что envучитывает $PATHпри поиске исполняемого файла). Это полезно, если исполняемый файл, который вы хотите вызвать, может находиться в разных местах на разных машинах. Например,
#!/usr/bin/env perl
в первой строке скрипта с установленным исполняемым битом этот скрипт будет выполняться с Perl, независимо от того, установлен он в /usr/bin/perlили в /usr/local/bin/perlдругом месте или в совершенно другом месте, если каталог находится в пути.
Конечно, поиск по пути сопряжен с дополнительным риском, но тогда риск не больше, чем если бы вы написали явно perl yourscript.pl, что также ищет perl в пути поиска.
В другой раз, когда envэто действительно полезно, вы хотите полностью контролировать окружающую среду. Я запускаю серверную программу (Informix, если вы не можете догадаться), окружение которой я хочу полностью контролировать. Я запускаю его, используя envв конце скрипта, который устанавливает кучу переменных на правильные значения:
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 "$@"
-iВариант существующей хочет подарить Петербург окружающей среды. Последующие VAR=valueпараметры устанавливают переменные среды, которые я хочу установить; имя программы находится в $ONINIT, и любые аргументы командной строки передаются через дословно с "$@".
${IXH:+INFORMIXSQLHOSTS="$IXH"}Конструкция проходит только INFORMIXSQLHOSTS="$IXH"в envслучае $IXHустанавливается в непустое значение.