В чем разница между set, export и env и когда мне следует использовать каждый из них?

Время от времени я собираю сценарий bash, и мне кажется, что есть несколько способов установки переменной:

key=value
env key=value
export key=value

Когда вы находитесь внутри скрипта или отдельной команды (например, я часто связываю переменную с помощью средства запуска Wine для установки правильного префикса Wine), они кажутся полностью взаимозаменяемыми, но, конечно, это не может иметь место.

В чем разница между этими тремя методами, и можете ли вы привести пример, когда я бы хотел использовать каждый из них?

Определенно связано с тем, В чем разница между `VAR=...` и `export VAR=...`? но я хочу знать как env тоже вписывается в это, и некоторые примеры, показывающие преимущества каждого из них, тоже были бы хорошими:)

1 ответ

Решение

Давайте рассмотрим конкретный пример. grep Команда использует переменную среды с именем GREP_OPTIONS установить параметры по умолчанию.

Сейчас. Учитывая, что файл test.txt содержит следующие строки:

line one
line two

запуск команды grep one test.txt вернусь

line one

Если вы запустите grep с -v опция, он будет возвращать несовпадающие строки, поэтому вывод будет

line two

Теперь мы попытаемся установить параметр с переменной среды.

  1. Переменные среды установлены без export не будет наследоваться в среде команд, которые вы вызываете.

    GREP_OPTIONS='-v'
    grep one test.txt
    

    Результат:

    line one
    

    Очевидно, что вариант -v не был передан grep,

    Вы хотите использовать эту форму, когда вы устанавливаете переменную только для оболочки, например, в for i in * ; do вы не хотите экспортировать $i ,

  2. Тем не менее, переменная передается в среду этой конкретной командной строки, так что вы можете сделать

    GREP_OPTIONS='-v' grep one test.txt
    

    который вернет ожидаемое

    line two
    

    Вы используете эту форму для временного изменения среды данного конкретного экземпляра запущенной программы.

  3. Экспорт переменной приводит к наследованию переменной:

    export GREP_OPTIONS='-v'
    grep one test.txt
    

    возвращается сейчас

    line two
    

    Это наиболее распространенный способ установки переменных для использования впоследствии запущенных процессов в оболочке.

  4. Все это было сделано в Bash. export это встроенный bash; VAR=whatever это синтаксис bash env С другой стороны, это программа сама по себе. когда env называется, происходят следующие вещи:

    1. Команда env исполняется как новый процесс
    2. env модифицирует окружающую среду и
    3. вызывает команду, указанную в качестве аргумента. env процесс заменяется command процесс.

    Пример:

    env GREP_OPTIONS='-v' grep one test.txt
    

    Эта команда запустит два новых процесса: (i) env и (ii) grep (фактически, второй процесс заменит первый). С точки зрения grep процесс, результат точно такой же, как работает

    GREP_OPTIONS='-v' grep one test.txt
    

    Тем не менее, вы можете использовать эту идиому, если вы находитесь за пределами bash или не хотите запускать другую оболочку (например, когда вы используете exec() семейство функций, а не system() вызов).

Дополнительная заметка о #!/usr/bin/env

Это также, почему идиома #!/usr/bin/env interpreter используется, а не #!/usr/bin/interpreter, env не требует полного пути к программе, потому что он использует execvp() функция, которая ищет через PATH переменная, как это делает оболочка, а затем заменяет себя командой run. Таким образом, его можно использовать, чтобы узнать, где интерпретатор (например, perl или python) "сидит" на пути.

Это также означает, что, изменяя текущий путь, вы можете влиять на то, какой вариант Python будет вызываться. Это делает возможным следующее:

echo -e '#!/usr/bin/bash\n\necho I am an evil interpreter!' > python
chmod a+x ./python
export PATH=.
calibre

вместо запуска Caliber, приведет к

I am an evil interpreter!
Другие вопросы по тегам