Javascript 使用Windows PowerShell传递Node.js环境变量

Javascript 使用Windows PowerShell传递Node.js环境变量,javascript,node.js,windows,powershell,Javascript,Node.js,Windows,Powershell,我正在尝试通过PowerShell将环境变量传递到Node.js,如下所示: C:\Users\everton\my-project> $env:MY_VAR = 8000 node index.js 但我在PowerShell中遇到一个错误: 标记“节点”意外的表达式或语句 首先设置环境变量MY_VAR,然后按如下方式运行应用程序: C:\Users\everton\my-project> $env:MY_VAR="8000" ; node index.js 您可以通过以下方式

我正在尝试通过PowerShell将环境变量传递到Node.js,如下所示:

C:\Users\everton\my-project> $env:MY_VAR = 8000 node index.js
但我在PowerShell中遇到一个错误:

标记“节点”意外的表达式或语句


首先设置环境变量MY_VAR,然后按如下方式运行应用程序:

C:\Users\everton\my-project> $env:MY_VAR="8000" ; node index.js
您可以通过以下方式访问环境变量
MY_VAR
inside
index.js

process.env.MY_VAR
注意:PowerShell不直接支持命令范围的环境变量。上面的命令为该PosikSession会话设置了环境变量。

注释:如果您可以假设NoDE.js已经安装了——正如定义的那样,当您调用<代码>节点< /代码>时,考虑使用<代码> NPM < /Cord>助手包,如 此答案主要关注PowerShell内部的通用解决方案

tl;dr

# Set env. variable temporarily, invoke the external utility, remove / restore old value.
$oldVal, $env:MYVAR = $env:MYVAR, 8000; node index.js; $env:MYVAR = $oldVal

# More structured alternative that uses a local 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

# More structured alternative
& { $env:MY_VAR=8000; node index.js; $env:MY_VAR=$null }
请参见下面的说明和基于辅助函数的替代方法


补充:

PowerShell没有与POSIX-like Shell提供的传递环境变量的命令范围方法等效的方法(从PowerShell v7开始-但是,将其引入PowerShell-不一定使用相同的语法-正在中讨论);e、 g:

#例如,在*Bash*:
#为正在调用的子进程(`node`)定义环境变量MY_VAR
#只有;换句话说:MY_VAR的作用域是被调用的命令
#(后续命令看不到它)。
MY_VAR=8000 node index.js
在PowerShell中,正如Harikrishnan的回答所示,必须首先定义环境变量,然后在单独的语句中调用外部程序,因此
$env:MY_VAR=“8000”;node index.js是正确的PowerShell解决方案,但是对于会话的剩余部分(设置在进程级别)而言,
$env:MY_VAR
停留在范围内是毫无价值的

请注意,即使使用通过
&
调用的脚本块来创建子作用域在这里也没有帮助,因为这样的子作用域只适用于PowerShell变量,而不适用于环境变量

当然,您可以在
节点
调用
之后手动删除环境变量:
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
    ;一次分配给多个变量的技术(在某些语言中称为解构分配)在“分配多个变量”一节中解释

或者,使用下面的辅助函数,或者使用
尝试{…}最后{…}
方法,如我的示例所示


用于命令范围的环境修改的助手函数。 如果在下面定义了helper函数(请记住,函数定义必须在调用之前放置),则可以按如下方式实现对环境的命令范围修改:

# 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]
    }
  }
}
函数调用WithEnvironment{
调用WithEnvironment@{PORT=8080}{node index.js}
运行环境变量端口临时设置为8080的节点,其
以前的值(如果有)
#>
param(
[参数(必需)][System.Collections.IDictionary]$Environment,
[参数(必需)][scriptblock]$scriptblock
)
#基于哈希表修改环境并保存原始
#一个用于以后的修复。
$htOrgEnv=@{}
foreach($Environment.GetEnumerator()中的$kv){
$htOrgEnv[$kv.Key]=(获取项-EA SilentlyContinue“env:$($kv.Key)”).Value
设置项目“环境:$($kv.Key)”$kv.Value
}
#调用脚本块
试一试{
&$ScriptBlock
}最后{
#恢复原始环境。
foreach($Environment.GetEnumerator()中的$kv){
#注意:将环境变量设置为$null或“*”将删除它。
设置项目“环境:$($kv.Key)”$htOrgEnv[$kv.Key]
}
}
}

我的答案要求使用Node.js和npm库

…或者您只需省去编写晦涩难懂的WTF语言脚本的痛苦,使用命令范围(加上跨平台)的Node.js脚本之一:

  • (用于内联)

  • (来自.env文件)


这为整个“bash”会话设置了命令,这不是命令范围,值得一提。同样值得一提的是我之前的评论。想象一下,有人来这里寻找生产环境的解决方案。他运行您的命令以排除事件故障,并使用
NODE\u ENV=dev
运行他的命令以获取NODE.js跟踪。他解决了问题,然后用
节点索引.js
重新启动服务器。除了他不知道自己还在
NODE_ENV=dev
中,并且在他的网站上的每个页面视图上都增加了500毫秒的延迟。合理的答案是“PowerShell无法做到这一点,请使用正确的工具或类似的解决方法”。您可以阅读此答案
cross-env MYVAR=MYVALUE node index.js
env-cmd .env node index.js
#.env file
MYVAR=MYVALUE