Яка різниця між набором, експортом та env, і коли я повинен використовувати їх?


112

Кожен так часто я вигадую скрипт bash, і це вражає мене, є кілька способів встановлення змінної:

key=value
env key=value
export key=value

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

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

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


5
Зауважте, що export key=valueрозширений синтаксис і не повинен використовуватися в портативних сценаріях (тобто #! /bin/sh).
Саймон Ріхтер

Відповіді:


110

Розглянемо конкретний приклад. 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. Це все робилося в баш. export- це вбудований баш; 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).

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

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

замість запуску Calibre призведе до

I am an evil interpreter!

Чому GREP_OPTIONS = '- v' grep один test.txt працює? Я подумав, що потрібен крапкою з комою після '-v' (але я спробував це, і він насправді спрацьовує.)
Джо

2
Тому що крапкою з комою він інтерпретується як дві окремі команди bash; перший встановлює змінну (не експортуючи її), а другий починає із середовища, яке не експортує змінну. Однак без крапки з комою це одна команда (grep), перед якою встановлюється локальне середовище.
січня

Звідки envберуться всі змінні ? Я маю на увазі, коли ви відкриваєте нову оболонку, у вас завжди є кілька змінних. Отже, якась програма повинна exportредагувати це, правда?
Пітікос

1
@Pithikos Змінні середовища встановлюються шляхом "пошуку середовища". За замовчуванням bash буде джерелом загальносистемного bashrc (або profile.d або bash_profile). Тоді він джерело вашого користувача ~ / .bashrc (та / або ~ / .bash_profile). Будь-який з цих файлів може містити bash команди для джерела інших сценаріїв, тому в кінцевому рахунку ви можете мати змінні середовища, що надходять з усіх куточків.
Ерік

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