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

发布于 2024-08-04 20:58:05 字数 374 浏览 3 评论 0原文

在Linux上,我可以这样做:

$ FOO=BAR ./myscript

在设置环境变量FOO的情况下调用“myscript”。

在 PowerShell 中是否可以进行类似的操作,即无需先设置变量、调用命令,然后再次取消设置变量?

为了更清楚地了解我的用例 - 我不想将其用作脚本的一部分。相反,我有一个第三方脚本,我可以使用环境变量来控制其行为,但在本例中,不能使用命令行参数。因此,能够在打字

$ OPTION=1 ./myscript

$ ./myscript

打字之间切换会非常方便。

On Linux, I can do:

$ FOO=BAR ./myscript

to call "myscript" with the environment variable FOO being set.

Is something similar possible in PowerShell, i.e. without having to first set the variable, call the command, and then unset the variable again?

To be more clear about my use case - I don't want to use this as part of a script. Rather, I have a third-party script whose behavior I can control using environment variables, but, in this case, not command line arguments. So being able to alternate between typing

$ OPTION=1 ./myscript

and

$ ./myscript

would just be very handy.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

如日中天 2024-08-11 20:58:05

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

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

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

Remove-Item Env:\FOO

Generally, it would be better to pass info to the script via a parameter rather than a
global (environment) variable. But if that is what you need to do you can do it this way:

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

The environment variable $env:FOO can be deleted later like so:

Remove-Item Env:\FOO
翻了热茶 2024-08-11 20:58:05

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

pwsh -Command { $env:MYVAR="myvalue"; .\path\to.exe }

Making a 'subshell' by invoking powershell with a script block allows you to scope the changes to the environment:

pwsh -Command { $env:MYVAR="myvalue"; .\path\to.exe }
一个人练习一个人 2024-08-11 20:58:05

两种简单的方法可以在一行中完成它:

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

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

2 easy ways to do it in a single line:

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

Just summarized information from other answers (thank you folks) which don't contain pure one-liners for some reason.

私野 2024-08-11 20:58:05

我对这个问题有足够的动力,所以我继续编写了一个脚本: 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< /code> 这可能比我上面编写的快速脚本更强大一些。

用法:

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

I got motivated enough about this problem that I went ahead and wrote a script for it: with-env.ps1

Usage:

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

On the other hand, if you install Gow you can use env.exe which might be a little more robust than the quick script I wrote above.

Usage:

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
玉环 2024-08-11 20:58:05

要完成与 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,我现在可以使用 app_master 环境变量集从命令行(包括其他参数)执行 cmd_special...执行命令后重置(甚至取消设置)。

据推测,您也可以针对单次调用临时执行此操作。

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

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

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

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

To accomplish the equivalent of the Unix syntax, you not only have to set the environment variable, but you have to reset it to its former value after executing the command. I've accomplished this for common commands I use by adding functions similar to the following to my PowerShell profile.

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

So mycmd is some executable that operates differently depending on the value of the environment variable app_master. By defining cmd_special, I can now execute cmd_special from the command line (including other parameters) with the app_master environment variable set... and it gets reset (or even unset) after execution of the command.

Presumably, you could also do this ad-hoc for a single invocation.

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

It really should be easier than this, but apparently this isn't a use-case that's readily supported by PowerShell. Maybe a future version (or third-party function) will facilitate this use-case. It would be nice if PowerShell had a cmdlet that would do this, e.g.:

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

Perhaps a PowerShell guru can suggest how one might write such a cmdlet.

抽个烟儿 2024-08-11 20:58:05

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

Start-Job -InitializationScript { $env:FOO = 'BAR' } -FilePath .\myscript.ps1 |
    Receive-Job -Wait -AutoRemoveJob

您还可以使用 Start-JobArgumentList 参数将参数传递给脚本:

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

优点和缺点

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

You could do this by running the script as a Job:

Start-Job -InitializationScript { $env:FOO = 'BAR' } -FilePath .\myscript.ps1 |
    Receive-Job -Wait -AutoRemoveJob

You could also pass arguments to the script, using the ArgumentList parameter of Start-Job:

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

Advantages and disadvantages

  • You don't have to reset the environment variable after the script finishes (which would require try / finally to do it correctly even in the presence of exceptions).
  • The environment variable will be really local to the launched script. It won't affect other, possibly launched in parallel, jobs.
  • The script will run in its own, somewhat isolated environment. This means that the launched script can't set variables of the main script, it has to write to the success stream (implicitly or by calling another command that already writes to the success stream) to communicate back to the main script. This could be an advantage or a disadvantage, depending on the use case.
奶气 2024-08-11 20:58:05

考虑到 CMD 是 Windows 内核上的本机 CLI(并且仍然是许多工具的自动化接口),您可以从 CMD 提示符或界面中使用 powershell.exe 执行 PowerShell 脚本接受 CMD 控制台语句。

如果您使用 -File 参数将脚本传递给 powershell.exe,则无法使用其他 PowerShell 代码来设置脚本访问的环境变量,因此相反,您可以在调用 powershell.exe 之前在 CMD 环境中设置环境变量:

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

单个 & 也可以工作,但如果 >set 由于某种原因失败。 (这可能吗?我不知道。)

此外,将 "foo=bar" 用引号括起来可能更安全,这样后面的任何内容都不会传递给 set 作为变量内容。

Considering that CMD is the native CLI on the Windows kernel (and is still the automation interface for lots of tools), you may be executing your PowerShell script with powershell.exe from the CMD prompt or an interface that accepts CMD console statements.

If you are using the -File parameter to pass your script to powershell.exe, no other PowerShell code can be used to set an environment variable for the script to access, so instead you can set your environment variables in the CMD environment before calling powershell.exe:

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

A single & will also work, but will allow the command to continue if the set failed for some reason. (Is this even possible? I have no idea.)

Also, it may be safer to wrap "foo=bar" in quotes so that nothing following gets passed to set as the variable contents.

断念 2024-08-11 20:58:05

在我的用例中,我需要设置一个环境变量,以便我可以在 Docker Compose 脚本中使用它。在我的 Powershell 脚本中,我使用分号定义变量,然后

$env:PLATFORM="linux/x86_64" ; docker-compose up -d --build

在 docker compose 中的同一行上调用 docker-compose 我现在可以使用我的 ${PLATFORM} 变量。

看起来像这样

...
services:
  zookeeper:
    image: confluentinc/cp-zookeeper:latest
    platform: ${PLATFORM}
...

In my use case I needed to set an environment variable so I can use it within a Docker Compose script. within my Powershell Script I define the variable use a semicolon then call docker-compose on same line

$env:PLATFORM="linux/x86_64" ; docker-compose up -d --build

within docker compose I can now just use my ${PLATFORM} variable.

which looks like this

...
services:
  zookeeper:
    image: confluentinc/cp-zookeeper:latest
    platform: ${PLATFORM}
...
北风几吹夏 2024-08-11 20:58:05

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

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

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

You can scope variables to functions and scripts.

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

New-Variable also has a -scope parameter if you want to be formal and declare your variable using new-variable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文