Powershell:仅为单个命令设置环境变量

mir*_*e2k 74 windows variables environment powershell scripting

在Linux上,我可以这样做:

$ FOO=BAR ./myscript
Run Code Online (Sandbox Code Playgroud)

在设置环境变量FOO的情况下调用"myscript".

在Powershell中是否有类似的可能,即无需先设置变量,调用命令,然后再次取消设置变量?

为了更清楚我的用例 - 我不想将它作为脚本的一部分使用.相反,我有一个第三方脚本,其行为我可以使用环境变量控制,但在这种情况下,不是命令行参数.因此能够在打字之间交替

$ OPTION=1 ./myscript
Run Code Online (Sandbox Code Playgroud)

$ ./myscript
Run Code Online (Sandbox Code Playgroud)

会非常方便.

gol*_*vok 38

通过使用脚本块调用 powershell 来创建“子 shell”,可以让您确定环境更改的范围:

pwsh -Command { $env:MYVAR="myvalue"; .\path\to.exe }
Run Code Online (Sandbox Code Playgroud)

  • 除了难以使用的“Start-Job”答案之外,这是唯一不会污染全球环境的答案,即使是短暂的。 (3认同)
  • 也许您需要使用“powershell”而不是“pwsh”。 (2认同)
  • @Andreas,[`pwsh`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_pwsh) 是 [_PowerShell (Core) 7+_ 的可执行文件名称](https://github.com/PowerShell/PowerShell/blob/master/README.md)。在内置 _Windows PowerShell_ 中,使用“powershell.exe”。(这两个 CLI 在参数方面基本相同。)如果要调用当前会话下的同一可执行文件,请使用 `& (Get-Process -Id $PID).Path { $env:MYVAR="myvalue" ; .\path\to.exe }`。您会因为启动另一个 PowerShell 实例而付出性能损失。 (2认同)

Kei*_*ill 36

通常,最好通过参数而不是全局(环境)变量将信息传递给脚本.但如果这是你需要做的,你可以这样做:

$env:FOO = 'BAR'; ./myscript
Run Code Online (Sandbox Code Playgroud)

环境变量$ env:FOO可以稍后删除,如下所示:

Remove-Item Env:\FOO
Run Code Online (Sandbox Code Playgroud)

  • 正如@Joey提到的,如果你想干净地执行环境变量,你可以: `& {$pre = $env:foo; $env:foo = '酒吧'; ./myscript; if ($pre) {$env:foo = $pre} else {Remove-Item env:\foo}`...有些人可能会说_unwieldy_,但会避免副作用... (5认同)
  • 您是否不需要将 `env:foo` 设置回其旧值(可能未设置)而不是删除它? (3认同)
  • 只是一个想法:难道你不能只生成一个新的PowerShell进程,通过-Command参数将scriptblock交给它吗?这样,您不必在之后清理环境,因为它将包含在子进程中.虽然我正在与PowerShell MVP交谈所以这可能不起作用:-) (2认同)
  • Keith,我们在Pscx中有一个推送环境块和pop-environmentblock正好适合这种情况;-) (2认同)
  • 约翰内斯,这也会起作用但不知何故似乎在作弊.:-) PSCX Push/Pop-EnvironmentBlock(一个*I*改为以这种方式工作)可以工作,但它没有scriptblock具有的自动清理支持. (2认同)

Ale*_*eev 16

在一行中完成的 2 种简单方法:

$env:FOO='BAR'; .\myscript; $env:FOO=''
$env:FOO='BAR'; .\myscript; Remove-Item Env:\FOO
Run Code Online (Sandbox Code Playgroud)

只是总结了其他答案(谢谢大家)中的信息,这些答案由于某种原因不包含纯单行。

  • 不起作用 - 变量未被删除。 (7认同)
  • 使用 `$env:FOO=$null` 而不是 `$env:FOO=''` (6认同)

Jas*_*mbs 10

要完成与 Unix 语法等效的功能,您不仅需要设置环境变量,而且还必须在执行命令后将其重置为以前的值。我通过向我的 PowerShell 配置文件添加类似于以下内容的函数,为我使用的常用命令完成了此操作。

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

一些可执行文件也是如此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 }
Run Code Online (Sandbox Code Playgroud)

它确实应该比这更容易,但显然这不是 PowerShell 很容易支持的用例。也许未来的版本(或第三方功能)将促进这个用例。如果 PowerShell 有一个可以执行此操作的 cmdlet,那就太好了,例如:

with-env app_master='http://host.example.com' mycmd
Run Code Online (Sandbox Code Playgroud)

也许 PowerShell 专家可以建议如何编写这样的 cmdlet。


kiz*_*zx2 7

我对这个问题有足够的动力,我继续写了一个脚本: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
Run Code Online (Sandbox Code Playgroud)

另一方面,如果您安装了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
Run Code Online (Sandbox Code Playgroud)


zet*_*t42 6

您可以通过将脚本作为Job运行来完成此操作:

Start-Job -InitializationScript { $env:FOO = 'BAR' } -FilePath .\myscript.ps1 |
    Receive-Job -Wait -AutoRemoveJob
Run Code Online (Sandbox Code Playgroud)

ArgumentList您还可以使用以下参数将参数传递给脚本Start-Job

$jobArgs = @{
    InitializationScript = { $env:FOO = 'BAR' } 
    FilePath             = '.\myscript.ps1'
    ArgumentList         = 'arg1', 'arg2' 
}
Start-Job @jobArgs | Receive-Job -Wait -AutoRemoveJob
Run Code Online (Sandbox Code Playgroud)

的优点和缺点

  • 您不必在脚本完成后重置环境变量(即使存在异常,这也需要try/才能正确执行)。finally
  • 环境变量对于启动的脚本来说将是真正的本地变量。它不会影响其他可能并行启动的作业。
  • 该脚本将在其自己的、有些隔离的环境中运行。这意味着启动的脚本无法设置主脚本的变量,它必须写入成功流(隐式或通过调用已写入成功流的另一个命令)以与主脚本通信。这可能是一个优点,也可能是一个缺点,具体取决于用例。


And*_*der -7

您可以将变量的范围限定为函数和脚本。

$script:foo = "foo"
$foo
$function:functionVariable = "v"
$functionVariable
Run Code Online (Sandbox Code Playgroud)

如果您想正式地使用 new-variable 声明变量,New-Variable 还有一个 -scope 参数。

  • 嗯...不认为这个答案适用于这里。PowerShell 变量不是环境变量。根据这个问题,提问者没有使用环境变量作为暂存空间(就像 CMD 中的那样[如果是这种情况,这个答案将适用]),但需要在调用外部命令之前操纵环境,然后恢复之后的环境(或类似的东西)。 (2认同)