web-dev-qa-db-fra.com

Passer la variable d'environnement Node.js avec Windows PowerShell

J'essaie de passer une variable d'environnement à Node.js avec PowerShell comme ceci:

C:\Users\everton\my-project> $env:MY_VAR = 8000 node index.js

Mais je reçois une erreur dans PowerShell:

Expression ou instruction inattendue de "nœud" de jeton

14
Everton Santos

Définir la variable d'environnement MY_VAR d'abord et exécutez votre application comme ceci:

C:\Users\everton\my-project> $env:MY_VAR="8000" ; node index.js

Vous pouvez accéder à la variable d'environnement MY_VAR à l'intérieur index.js par

process.env.MY_VAR

Remarque: PowerShell ne prend pas directement en charge les variables d'environnement à portée de commande. La commande ci-dessus définit la variable d'environnement pour cette session PowerShell.

18
Harikrishnan

Ma réponse nécessite l'utilisation de bibliothèques Node.js et npm.

... ou vous supprimez simplement la peine d'écrire des scripts en langage WTF obscur et utilisez l'un des scripts Node.js à portée de commande (plus multiplateforme):

  • cross-env (pour en ligne)

    cross-env MYVAR=MYVALUE node index.js
    
  • env-cmd (à partir du fichier .env)

    env-cmd .env node index.js
    

    avec

    #.env file
    MYVAR=MYVALUE
    
7
Cyril CHAPON

Remarque: Si vous pouvez supposer que Node.js est déjà installé - comme c'est par définition le cas lorsque vous invoquez node - pensez à utiliser npm packages d'assistance, comme indiqué dans réponse utile de Cyril CHAPON .
Ceci la réponse se concentre sur les solutions génériques depuis 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 }

Plus simplement, s'il n'y a pas de valeur MY_VAR Préexistante qui doit être restaurée.

$env:MYVAR=8000; node index.js; $env:MYVAR=$null

# More structured alternative
& { $env:MY_VAR=8000; node index.js; $env:MY_VAR=$null }

Voir ci-dessous pour une explication et une alternative basée sur une fonction d'assistance.


Pour compléter réponse efficace de Harikrishnan :

PowerShell a non équivalent à la méthode à portée de commande de transmission des variables d'environnement offertes par les shells POSIX ( (à partir de PowerShell v7 - cependant, l'introduire dans PowerShell - pas nécessairement avec la même syntaxe - est discuté dans ce problème GitHub ); par exemple.:

 # 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

Dans PowerShell, comme le montre la réponse de Harikrishnan, vous devez définir la variable d'environnement d'abord, puis, dans une instruction séparée =, appelez le programme externe , donc $env:MY_VAR="8000"; node index.js est la bonne solution PowerShell, mais cela ne vaut rien $env:MY_VAR reste dans la portée pour le reste de la session (il est défini au niveau process).

Notez que même l'utilisation d'un bloc de script appelé avec & Pour créer une portée enfant n'aide pas ici, car ces portées enfants ne s'appliquent qu'aux variables PowerShell, pas environnement variables.

Vous pouvez bien sûr supprimer la variable d'environnement manuellement après l'appel node:
Remove-Item env:MY_VAR Ou même simplement $env:MY_VAR = $null, C'est ce que montre la 1ère commande en haut.


Une alternative plus structurée - peut-être meilleure dans le cas de la définition de variables d'environnement multiple et/ou d'invocation de plusieurs commandes - est pour utiliser un bloc de script appelé avec &:

& { $oldVal, $env:MY_VAR = $env:MY_VAR, 8000; node index.js; $env:MY_VAR = $oldVal }

Cela profite de:

  • { ... } Est un bloc de script qui fournit un regroupement clairement visible pour les commandes qu'il contient; invoqué avec &, il crée une portée locale, de sorte que la variable d'assistance $oldVal sort automatiquement de la portée à la sortie du bloc.

  • $oldVal, $env:MY_VAR = $env:MY_VAR, 8000 Enregistre l'ancienne valeur (le cas échéant) de $env:MY_VAR Dans $oldVal Tout en changeant la valeur en 8000; cette technique d'affectation à plusieurs variables à la fois (connue sous le nom affectation destructurante dans certaines langues) est expliquée dans Get-Help about_Assignment_Operators , section "ASSIGNING MULTIPLE VARIALBES" .

Alternativement , utilisez la fonction d'assistance ci-dessous , ou utilisez un try { ... } finally { ... } approche, comme démontré dans cette réponse connexe à moi.


Fonction d'assistance pour les modifications d'environnement à portée de commande.

Si vous définissez la fonction d'assistance ci-dessous (rappelez-vous que les définitions de fonction doivent être placées avant elles sont invoquées), vous pouvez effectuer la modification de votre environnement au niveau des commandes comme suit:

# Invoke `node index.js` with a *temporarily* set MY_VAR environment variable.
Invoke-WithEnvironment @{ MY_VAR = 8000 } { node index.js }

Invoke-WithEnvironment() code source :

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]
    }
  }
}
5
mklement0