Что-то вроде побочного вопроса, но как называется эта функция, когда вы устанавливаете переменную окружения для одной подобной подкоманды? Мне всегда было трудно найти информацию об этом, потому что я не знаю, как это называется.
@JohnCromartie Это необязательный компонент каждой команды оболочки, поэтому он находится в разделе «Простые команды» большинства руководств по оболочке. Для POSIX это было бы здесь . Гленн связал аналогичный раздел из руководства по bash для вас.
jw013
Установка переменной, которая не существует с помощью присваивания, создает переменную оболочки. Установка его через ENV или экспорт переменной помещает переменную в среду выполнения оболочки. Изменение значения существующей переменной обновит значение среды выполнения, если оно существует, в противном случае измените его во внутренних переменных оболочки.
Йохан
Ответы:
26
Они функционально эквивалентны.
Основное различие заключается в том, что вы 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что-то используете, это использует ваше текущее окружение?
Гленн Джекман
1
Так же @StephaneChazelas, и вы также sudo FOO=bar bazможете передавать переменные окружения без необходимости env.
Майк Миллер
1
@StephaneChazelas, который работает, только если я хочу вставить FOO=barв сценарий. Если FOOне всегда bar, я не хочу жестко его кодировать, а вместо этого передать.
Патрик
@glennjackman да, да, если переменные экспортируются или передаются до exec, например FOO=bar exec baz.
Патрик
14
В этом конкретном примере нет эффективной разницы, если предположить, что ваша оболочка является POSIX-совместимой оболочкой, и предполагается, bazчто это исполняемый файл, а не встроенная оболочка.
Если ваша оболочка не является POSIX-совместимой оболочкой, например, cshили tcsh, синтаксис
FOO=bar baz
не работает, и нет эквивалентного синтаксиса оболочки. Для этих оболочек envкоманда является единственным способом переопределить или внедрить переменные среды для одной команды.
Если bazэто встроенная оболочка, скажем, fcнапример, то envона не даст таких же результатов, потому что envвыполняет новый процесс вместо того, чтобы запускаться непосредственно командной оболочкой. Более того, fcисполняемого файла нет , его можно запускать только как встроенную оболочку из-за того, как он взаимодействует со средой оболочки и поэтому никогда неenv будет работать со встроенным подобным .fc
Кроме того, envпредлагается -iопция, позволяющая запустить команду в пустой среде только с указанным набором переменных среды. Так что envможет быть очень полезным для запуска процессов в санитарных средах, например
Когда я использовал, tcshя писал, (setenv FOO bar; baz)чтобы получить эквивалентную функцию.
Бармар
6
В дополнение к тому, что уже было сказано
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в конце скрипта, который устанавливает кучу переменных на правильные значения:
-iВариант существующей хочет подарить Петербург окружающей среды. Последующие VAR=valueпараметры устанавливают переменные среды, которые я хочу установить; имя программы находится в $ONINIT, и любые аргументы командной строки передаются через дословно с "$@".
${IXH:+INFORMIXSQLHOSTS="$IXH"}Конструкция проходит только INFORMIXSQLHOSTS="$IXH"в envслучае $IXHустанавливается в непустое значение.
Ответы:
Они функционально эквивалентны.
Основное различие заключается в том, что вы
env FOO=bar baz
вызываете промежуточный процесс между оболочкой иbaz
, как и в случае сFOO=bar baz
оболочкой, напрямуюbaz
.Так что в этом отношении
FOO=bar baz
предпочтительнее.Единственные ситуации, в которых я нахожусь,
env FOO=bar
- это когда я должен передать команду другой команде.В качестве конкретного примера, допустим, у меня есть скрипт-обертка, который выполняет некоторые модификации среды, а затем вызывает
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
, синтаксисне работает, и нет эквивалентного синтаксиса оболочки. Для этих оболочек
env
команда является единственным способом переопределить или внедрить переменные среды для одной команды.Если
baz
это встроенная оболочка, скажем,fc
например, тоenv
она не даст таких же результатов, потому чтоenv
выполняет новый процесс вместо того, чтобы запускаться непосредственно командной оболочкой. Более того,fc
исполняемого файла нет , его можно запускать только как встроенную оболочку из-за того, как он взаимодействует со средой оболочки и поэтому никогда неenv
будет работать со встроенным подобным .fc
Кроме того,
env
предлагается-i
опция, позволяющая запустить команду в пустой среде только с указанным набором переменных среды. Так чтоenv
может быть очень полезным для запуска процессов в санитарных средах, напримеристочник
tcsh
я писал,(setenv FOO bar; baz)
чтобы получить эквивалентную функцию.В дополнение к тому, что уже было сказано
Будучи функцией оболочки (Bourne / POSIX), вы ограничены в именах переменных среды, которые вы передаете
cmd
. Они должны быть допустимыми именами переменных оболочки и не должны быть только для чтения или специальными переменными для оболочки.Например, вы не можете сделать:
Или
bash
не позволяет вам делать:Пока вы можете сделать:
(не то, что вы хотите или должны хотеть сделать это). Или:
(Мне иногда нужно это делать).
Обратите внимание, что
env
вы по-прежнему не можете передать строку переменной среды, которая не содержит=
(не то, что вы хотели бы сделать это либо).источник
Одним из применений
env
является возможность$PATH
поиска исполняемых файлов в строках shebang (потому чтоenv
учитывает$PATH
при поиске исполняемого файла). Это полезно, если исполняемый файл, который вы хотите вызвать, может находиться в разных местах на разных машинах. Например,в первой строке скрипта с установленным исполняемым битом этот скрипт будет выполняться с Perl, независимо от того, установлен он в
/usr/bin/perl
или в/usr/local/bin/perl
другом месте или в совершенно другом месте, если каталог находится в пути.Конечно, поиск по пути сопряжен с дополнительным риском, но тогда риск не больше, чем если бы вы написали явно
perl yourscript.pl
, что также ищет perl в пути поиска.источник
В другой раз, когда
env
это действительно полезно, вы хотите полностью контролировать окружающую среду. Я запускаю серверную программу (Informix, если вы не можете догадаться), окружение которой я хочу полностью контролировать. Я запускаю его, используяenv
в конце скрипта, который устанавливает кучу переменных на правильные значения:-i
Вариант существующей хочет подарить Петербург окружающей среды. ПоследующиеVAR=value
параметры устанавливают переменные среды, которые я хочу установить; имя программы находится в$ONINIT
, и любые аргументы командной строки передаются через дословно с"$@"
.${IXH:+INFORMIXSQLHOSTS="$IXH"}
Конструкция проходит толькоINFORMIXSQLHOSTS="$IXH"
вenv
случае$IXH
устанавливается в непустое значение.источник