В чем разница между командами
$ 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
устанавливается в непустое значение.