【发布时间】:2017-03-26 04:13:44
【问题描述】:
我正在尝试使用 PowerShell 将环境变量传递给 Node.js,如下所示:
C:\Users\everton\my-project> $env:MY_VAR = 8000 node index.js
但我在 PowerShell 中遇到错误:
令牌“节点”意外表达式或语句
【问题讨论】:
标签: javascript node.js windows powershell
我正在尝试使用 PowerShell 将环境变量传递给 Node.js,如下所示:
C:\Users\everton\my-project> $env:MY_VAR = 8000 node index.js
但我在 PowerShell 中遇到错误:
令牌“节点”意外表达式或语句
【问题讨论】:
标签: javascript node.js windows powershell
首先设置环境变量MY_VAR,然后像这样运行你的应用:
C:\Users\everton\my-project> $env:MY_VAR="8000" ; node index.js
您可以通过
访问index.js内的环境变量MY_VAR
process.env.MY_VAR
注意:PowerShell 不直接支持命令范围的环境变量。上述命令为该 PowerShell 会话设置环境变量。
【讨论】:
NODE_ENV=dev 运行他的命令以获取 node.js 跟踪。他解决了这个问题,然后用node index.js 重新启动了他的服务器。除了他不知道他还在NODE_ENV=dev 中,并且在他的网站上的每个页面视图上增加了 500 毫秒的延迟。合理的答案是“PowerShell 做不到,请使用正确的工具或像这样的解决方法”
注意:如果您可以假设 Node.js 已经安装 - 根据定义,当您调用 node 时的情况 - 考虑使用 npm 帮助程序包,如Cyril CHAPON 's helpful answer 中所示。
此答案侧重于 PowerShell 中的通用解决方案。
tl;dr
# Set env. variable temporarily, invoke the external utility,
# then remove / restore old value.
$oldVal, $env:MYVAR = $env:MYVAR, 8000; node index.js; $env:MYVAR = $oldVal
# Scoped alternative that uses a *transient* helper variable.
& { $oldVal, $env:MY_VAR = $env:MY_VAR, 8000; node index.js; $env:MY_VAR = $oldVal }
更简单地说,如果没有必须恢复的预先存在的 MY_VAR 值。
$env:MYVAR=8000; node index.js; $env:MYVAR=$null
请参阅下面的解释和基于辅助函数的替代方法。
补充Harikrishnan's effective answer:
PowerShell no 等效于 command-scoped 方法来传递类似 POSIX 的 shell 提供的环境变量(从 PowerShell v7 开始 -但是,将它引入 PowerShell - 不一定使用相同的语法 - 正在 GitHub issue #3316 中讨论);例如:
# E.g., in *Bash*:
# Define environment variable MY_VAR for the child process being invoked (`node`)
# ONLY; in other words: MY_VAR is scoped to the command being invoked
# (subsequent commands do not see it).
MY_VAR=8000 node index.js
在 PowerShell 中,正如 Harikrishnan 的回答所示,您必须先定义环境变量,然后在单独的语句中调用外部程序,所以$env:MY_VAR="8000"; node index.js 是正确的 PowerShell 解决方案,但是 $env:MY_VAR 留在范围内对于 session 的剩余部分(它设置在 process 级别)。
请注意,即使使用& 调用的脚本块来创建子范围也无济于事,因为此类子范围仅适用于 PowerShell 变量,不适用于 环境 em> 变量。
当然,您可以在调用node之后手动删除环境变量:Remove-Item env:MY_VAR 甚至只是$env:MY_VAR = $null,即顶部的第一个命令显示的内容。
更有条理的替代方案 - 在设置 多个 环境变量和/或调用多个命令的情况下可能更好 - 是使用通过 & 调用的脚本块:
& { $oldVal, $env:MY_VAR = $env:MY_VAR, 8000; node index.js; $env:MY_VAR = $oldVal }
这利用了:
{ ... } 是一个脚本块,它为其中的命令提供了清晰可见的分组;使用& 调用时,它会创建一个本地范围,以便辅助变量$oldVal 在退出块时自动超出范围。
$oldVal, $env:MY_VAR = $env:MY_VAR, 8000 将$env:MY_VAR 的旧值(如果有)保存在$oldVal 中,同时将值更改为8000;这种一次性分配给多个变量的技术(在某些语言中称为解构分配)在Get-Help about_Assignment_Operators,“分配多个变量”部分中进行了说明。
或者,使用下面的帮助函数,或使用try { ... } finally { ... }方法,如this related answer所示。
如果您在下面定义辅助函数(请记住,函数定义必须放在它们被调用之前),您可以实现对环境的命令范围修改,如下所示:
# Invoke `node index.js` with a *temporarily* set MY_VAR environment variable.
Invoke-WithEnvironment @{ MY_VAR = 8000 } { node index.js }
Invoke-WithEnvironment()源码:
function Invoke-WithEnvironment {
<#
.SYNOPSIS
Invokes commands with a temporarily modified environment.
.DESCRIPTION
Modifies environment variables temporarily based on a hashtable of values,
invokes the specified script block, then restores the previous environment.
.PARAMETER Environment
A hashtable that defines the temporary environment-variable values.
Assign $null to (temporarily) remove an environment variable that is
currently set.
.PARAMETER ScriptBlock
The command(s) to execute with the temporarily modified environment.
.EXAMPLE
> Invoke-WithEnvironment @{ PORT=8080 } { node index.js }
Runs node with environment variable PORT temporarily set to 8080, with its
previous value, if any
#>
param(
[Parameter(Mandatory)] [System.Collections.IDictionary] $Environment,
[Parameter(Mandatory)] [scriptblock] $ScriptBlock
)
# Modify the environment based on the hashtable and save the original
# one for later restoration.
$htOrgEnv = @{}
foreach ($kv in $Environment.GetEnumerator()) {
$htOrgEnv[$kv.Key] = (Get-Item -EA SilentlyContinue "env:$($kv.Key)").Value
Set-Item "env:$($kv.Key)" $kv.Value
}
# Invoke the script block
try {
& $ScriptBlock
} finally {
# Restore the original environment.
foreach ($kv in $Environment.GetEnumerator()) {
# Note: setting an environment var. to $null or '' *removes* it.
Set-Item "env:$($kv.Key)" $htOrgEnv[$kv.Key]
}
}
}
【讨论】: