Заздрити чи не заздрити


32

Яка різниця між командою

$ env FOO=bar baz

і

$ FOO=bar baz

Який ефект envмає?


4
Сортування побічного питання, але як називається сама функція, коли ви встановлюєте змінну середовища для однієї такої підкоманди? Мені завжди важко було знайти інформацію про це, тому що я не знаю, як це називається.
Джон Кромарті

1
@JohnCromartie, ви повинні поставити це як питання.
CJM

1
Для баш, це задокументовано тут: gnu.org/software/bash/manual/…
glenn jackman

2
@JohnCromartie Це необов'язковий компонент кожної команди оболонки, тому вона знаходиться в розділі "Прості команди" у більшості посібників із оболонками. Для POSIX це було б тут . glenn пов’язав аналогічний розділ із посібника з 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, і цілком дійсне.


1
Ви можете зробити це, FOO=bar exec bazхоча вам не потрібно envв останній точці.
Стефан Шазелас

Коли ви execщось, чи використовує це ваше поточне оточення?
Глен Джекман

1
Ditto @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може бути дуже корисно, наприклад, для запуску процесів у санітарних умовах

env -i HOME=/tmp/homedir "PATH=`getconf PATH`" "TERM=$TERM" FOO=bar baz

Коли я використовував, 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вами все ще не можна передавати рядок змінної середовища, яка не містить =(не те, що ви хотіли б зробити так).


2

Одне використання env- дозволити $PATHпошук виконуваних файлів у рядках shebang (тому що envвраховується $PATHпри пошуку виконуваного файлу). Це корисно, якщо виконуваний файл, який ви хочете викликати, може знаходитися в різних місцях на різних машинах. Наприклад,

#!/usr/bin/env perl

у першому рядку сценарію з набором виконуваних бітів буде виконуватися цей скрипт за допомогою Perl, незалежно від того, встановлений він у, /usr/bin/perlабо в ньому, /usr/local/bin/perlабо в зовсім іншому місці, доки каталог буде в шляху.

Звичайно, пошук шляхів пошуку має додатковий ризик, але тоді ризик не більший, ніж якби ви прямо написали perl yourscript.pl, що також шукає перл на шляху пошуку.


2

Інший час, коли 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встановлюється в непорожнє значення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.