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


99

У Linux я можу:

$ FOO=BAR ./myscript

викликати "myscript" при встановленій змінній середовища FOO.

Чи можливо щось подібне в PowerShell, тобто, не спочатку встановлюючи змінну, викликати команду, а потім знову скинути змінну?

Щоб бути більш зрозумілим щодо мого випадку використання - я не хочу використовувати це як частину сценарію. Швидше, у мене є сторонній скрипт, поведінку якого я можу контролювати, використовуючи змінні середовища, але, в цьому випадку, не аргументи командного рядка. Тож можна чергувати між набором тексту

$ OPTION=1 ./myscript

і

$ ./myscript

просто було б дуже зручно.


Я думаю, моє запитання було б, чому вам потрібно це робити? Я б подумав, що краще рішення є.
EBGreen

20
Зазвичай це не корисне питання, @EBGreen. Той факт, що дієздатність є в оболонках UNIX, говорить про те, що для цього є користь. Зверху в голові: контроль імені користувача та електронної адреси, який git використовує для комітетів. Для них немає параметра командного рядка - їх потрібно встановити у ~ / .gitconfig, .git / config у кожному сховищі або envars. З цих варіантів envars очевидно простіше встановити під час руху (і зручно переосмислити значення у файлах). Отже, якщо я хочу змінити ім'я автора на один "git počin" в powerhell, як це зробити?
Марк Рід

2
Повністю погоджуйтеся, що питати, для чого це потрібно, безглуздо. Це так само часто, як борщ при виконанні командного рядка в Linux, і тим, хто з нас змушений зараз страждати з патрон силів (синтаксичний кошмар, якщо такий взагалі існував), постійно доводиться шукати відповіді на очевидні методи. Здебільшого вони відсутні; вони навіть існують в оболонці, якщо ви не рахуєте написання довгих сценаріїв, щоб робити тривіальні речі. Порахуйте мене глибоко розчарованим цією оболонкою ...
Кім


1
Дякуємо за посилання, @FranklinYu, але на даний момент це буде, сподіваємось, у не надто віддаленій майбутній версії після v7.0 .
mklement0

Відповіді:


54

Як правило, було б краще передавати інформацію скрипту за допомогою параметра, а не глобальної змінної (оточення). Але якщо це те, що вам потрібно зробити, ви можете зробити це так:

$env:FOO = 'BAR'; ./myscript

Змінна середовища $ env: FOO можна пізніше видалити так:

Remove-Item Env:\FOO

2
Подумка: Ви не могли просто нерестувати новий процес PowerShell, передаючи в нього блокблок через параметр -Command? Таким чином, вам не доведеться потім прибирати навколишнє середовище, оскільки це буде міститися в дочірньому процесі. Хоча я розмовляю з PowerShell MVP, тому це, мабуть, не працює :-)
Joey

2
Кіт, у нас в Pscx є push-Environmentblock та pop-Environmentblock саме для цього сценарію ;-)
x0n

2
Йоганнес, це також спрацювало б, але якось схоже на обман. :-) PSCX Push / Pop-EnvironmentBlock (той, який я змінив, щоб зробити роботу таким чином), працював би, але він не підтримує автоматичну очистку, яку має сценарій.
Кіт Хілл

1
Чи не потрібно env:fooповертати його до старого значення (можливо, вимкнено), а не видаляти його?
chwarr

1
Як згадував @Joey, якщо ви хочете чисто робити env vars, ви могли б: & {$pre = $env:foo; $env:foo = 'bar'; ./myscript; if ($pre) {$env:foo = $pre} else {Remove-Item env:\foo}... дехто може сказати, що непросто , але уникнете побічних ефектів ...
Лукас,

13

Я досить мотивував цю проблему, що пішов наперед і написав для неї сценарій: with-env.ps1

Використання:

with-env.ps1 FOO=foo BAR=bar your command here

# Supports dot-env files as well
with-env.ps1 .\.env OTHER_ENV=env command here

З іншого боку, якщо ви встановите Gow, ви можете використовуватиenv.exe що може бути трохи більш надійним, ніж швидкий сценарій, про який я писав вище.

Використання:

env.exe FOO=foo BAR=bar your command here

# To use it with dot-env files
env.exe $(cat .env | grep.exe -v '^#') SOME_OTHER_ENV=val your command

4

Щоб виконати еквівалент синтаксису Unix, вам потрібно не лише встановити змінну середовища, але вам доведеться відновити її до колишнього значення після виконання команди. Це я зробив для загальних команд, які використовую, додавши функції, подібні до наведених нижче, до мого профілю PowerShell.

function cmd_special()
{
  $orig_master = $env:app_master
  $env:app_master = 'http://host.example.com'
  mycmd $args
  $env:app_master = $orig_master
}

Так mycmdє деякі виконувані файли, які працюють по-різному, залежно від значення змінної середовища app_master. Визначившись cmd_special, я зараз можу виконатиcmd_special з командного рядка (включаючи інші параметри) з app_masterнабором змінної середовища ... і він буде скинутий (або навіть знятий) після виконання команди.

Імовірно, ви також можете зробити це тимчасово для однієї виклику.

& { $orig_master = $env:appmaster; $env:app_master = 'http://host.example.com'; mycmd $args; $env:app_master = $orig_master }

Це дійсно повинно бути простіше, ніж це, але, мабуть, це не той випадок використання, який легко підтримує PowerShell. Можливо, майбутня версія (або стороння функція) полегшить цей варіант використання. Було б добре, якби у PowerShell був командлет, який би це зробив, наприклад:

with-env app_master='http://host.example.com' mycmd

Можливо, гуру PowerShell може підказати, як можна написати такий командлет.


3

2 прості способи зробити це в один рядок:

$env:FOO='BAR'; .\myscript; $env:FOO=''
$env:FOO='BAR'; .\myscript; Remove-Item Env:\FOO

Просто узагальнена інформація з інших відповідей (дякую людям), які з певних причин не містять чистих вкладишів.


0

Зважаючи на те, що CMD є нативним CLI в ядрі Windows (і досі це інтерфейс автоматизації для багатьох інструментів), ви можете виконувати свій скрипт PowerShell з powershell.exeпідказки CMD або інтерфейсу, який приймає консолі тверджень консолі CMD.

Якщо ви використовуєте -Fileпараметр для передачі свого скрипту powershell.exe, жоден інший код PowerShell не може бути використаний для встановлення змінної середовища для доступу скрипту, тому замість цього ви можете встановити змінні середовища в середовищі CMD перед викликом powershell.exe:

> set foo=bar && powershell.exe -File .\script.ps1

Сингл &також буде працювати, але дозволить команді продовжуватися, якщо з setякоїсь причини не вдалося. (Це можливо навіть? Я поняття не маю.)

Крім того, може бути безпечніше обгортати "foo=bar"лапки, щоб нічого з наступних не переходило до setвмісту змінної.



-5

Ви можете застосовувати змінні до функцій та сценаріїв.

$script:foo = "foo"
$foo
$function:functionVariable = "v"
$functionVariable

У New-Variable також є параметр -scope, якщо ви хочете бути формальним і оголосити свою змінну за допомогою new-змінної.


1
Гммм ... Не думаю, що ця відповідь стосується тут. Змінні PowerShell - це не змінні середовища. Виходячи з запитання, запитувач не використовує змінні середовища як простір подряпин (як, наприклад, у CMD (якщо так було, ця відповідь застосовуватиметься)), але йому потрібно маніпулювати середовищем перед тим, як викликати зовнішню команду, а потім відновити навколишнє середовище згодом (або щось для цього).
чвар
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.