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

80

Каждый раз так, что я выхожу из сценария bash, и мне кажется, что есть несколько способов установки переменной:

key=value
env key=value
export key=value

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

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

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

    
задан Oli 24.10.2012 в 11:34
источник

1 ответ

80

Рассмотрим конкретный пример. Команда 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 так же, как это делает оболочка, а затем сама заменяет на запуск команды , Таким образом, его можно использовать, чтобы выяснить, где интерпретатор (например, 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!
    
ответ дан January 24.10.2012 в 12:21
источник