Видаліть змінну середовища для однієї команди


24

Я можу запустити ENV_VAR=value commandбіг commandіз конкретним значенням для ENV_VAR. Що еквівалентно дезактивувати ENV_VARдля command?


7
Убік: commandце невдалий вибір заповнювачів, оскільки насправді є вбудована команда під цим іменем. mycommandабо somecommandабо таке може бути кращою звичкою заходити.
Чарльз Даффі

@CharlesDuffy, я зазвичай використовую cmdдля цього.
Стефан Шазелас

Відповіді:


35

Крім -iопції, яка стирає все середовище, POSIX envне дає жодного способу скинути змінну.

Однак, маючи кілька envреалізацій (включаючи busyboxпринаймні GNU, 'та FreeBSD), ви можете:

env -u ENV_VAR command

Що буде працювати при видаленні кожного екземпляра ENV_VARзмінної із середовища (зауважте, що вона не працює для змінної середовища з порожнім іменем ( env -u ''або дає помилку, або неефективна залежно від реалізації, хоча всі приймають env '=value', ймовірно, обмеження) виникає функцією unsetenv()C, якій POSIX вимагає повернути помилку для порожнього рядка, тоді як для цього немає обмеження putenv())).

Портативно (в оболонках POSIX) ви можете:

(unset -v ENV_VAR; exec command)

(зауважте, що з деякими оболонками, використовуючи execможе змінювати commandзапускається: запускає файлову систему замість функції або вбудований, наприклад, (і, очевидно, обійде aliasрозширення), як envвище. Ви хочете опустити це в цих випадках) .

Але це не буде працювати для змінних оточення, які мають ім'я, яке не можна приєднати до змінної оболонки (зауважте, що деякі оболонки, як-от як mkshби знімали ці змінні з оточення при запуску), або змінні, позначені лише для читання.

-vпризначений для оболонки Bourne, і без bashякої unsetне -vможна було б скинути ENV_VAR функцію, якби не було змінної за цією назвою. Більшість інших оболонок не скасує функції, якщо ви не передасте цей -fпараметр. (навряд чи змінить практику).

(Також остерігайтеся про помилку / помилковою особливості з bash/ mksh/ yashякого unset, при деяких обставини не можуть скинути змінні, але показують змінний у зовнішній області видимості )

Якщо perlє, ви можете зробити:

perl -e 'delete $ENV{shift@ARGV}; exec @ARGV or die$!' ENV_VAR command

Що буде працювати навіть для змінної середовища з порожнім ім'ям.

Тепер усі вони не працюватимуть, якщо ви хочете змінити змінну середовища для вбудованої або функції та не хочете, щоб вони працювали в підкашлі, як-от у bash:

env -u LANG printf -v var %.3f 1.2 # would run /usr/bin/printf instead
(unset -v LANG; printf -v var %.3f 1.2) # changes to $var lost afterwards

(тут вимкнення LANG як помилкового підходу при переконуванні .використовується і розуміється як десятковий роздільник. Було б краще використовувати LC_ALL=C printf...для цього)

За допомогою деяких оболонок ви можете замість цього створити локальну область для змінної за допомогою функції:

without() {
  local "$1" # $1 variable declared as initially unset in bash¹
  shift
  "$@"
}
without LANG printf -v var %.3f 1.2

З zsh, ви також можете використовувати анонімну функцію:

(){local ENV_VAR; command}

Такий підхід не буде працювати в деяких оболонках (як, наприклад, на основі оболонки Almquist), localякі не оголошують змінну як початкову не встановлену (але успадковують значення та атрибути). У цих випадках ви можете це робити local ENV_VAR; unset ENV_VAR, але не робіть цього в mkshабо yash( typesetзамість localцього), оскільки це не спрацювало б, це unsetбуло б лише скасуванням local.

¹ Також майте на увазі bash, що локальний ENV_VAR(навіть не встановлений) збереже експортний атрибут. Отже, якби commandбула функція, якій присвоюється значення ENV_VAR, змінна була б доступна в оточенні команд, викликаних згодом. unset ENV_VARзрозумів би цей атрибут. Або ви можете використовувати, local +x ENV_VARщо також забезпечить чистий діапазон (якщо тільки ця змінна не була оголошена лише для читання, але тоді ви нічого не можете з цим зробити bash).


1
Це окреме питання, але що, до біса, це змінна середовище з порожнім ім'ям, і як би ти коли-небудь використовував це - навіть для якогось подвигу? Чи не доведеться вам писати програму, яка читає оточення та спеціально шукає щось подібне?
Джо

@Joe, спробуйте, наприклад env '=foo' python -c 'import os; print os.environ[""]'. Я не думаю, що багато людей захочуть встановити подібну змінну.
Стефан Хазелас

9

Наскільки я не знаю прямого еквівалента; ви можете скористатися передплатою:

(unset ENV_VAR; exec command)

(unset ENV_VAR; exec somecommand)якщо ви хочете бути еквівалентними оригіналу за ефективністю (споживши нижню частину корпусу). Як це є, це додає додаткову вилку.
Чарльз Даффі

1
@Charles дійсно, хоча деякі оболонки роблять це автоматично, оскільки commandє останньою командою в виклику додаткової оболонки .
Стівен Кітт

+1, оскільки цей спосіб простий для введення в інтерактивне використання. Я використовую підшари для одноразових змін середовища оболонки для однокласника, а не пам'ятати, що це env -u.
Пітер Кордес

0

Можна використовувати ENV_VAR= command

Це насправді не скидає змінну, але вона може бути корисною у багатьох випадках (сценарії оболонки зазвичай просто використовують, test -nщоб перевірити, чи встановлена ​​змінна):

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