2009-09-14 11 views
41

Su Linux, non posso fare:PowerShell: Impostazione di una variabile d'ambiente per un singolo comando solo

$ FOO=BAR ./myscript 

a chiamare "mioscript" con l'FOO variabile d'ambiente da impostare.

È qualcosa di simile possibile in Powershell, vale a dire senza dover prima impostare la variabile, chiamare il comando e quindi annullare nuovamente la variabile?

Per essere più chiari sul mio caso d'uso, non voglio usarlo come parte di uno script. Piuttosto, ho uno script di terze parti il ​​cui comportamento posso controllare usando le variabili d'ambiente, ma, in questo caso, non gli argomenti della riga di comando. Quindi, essendo in grado di alternare la digitazione

$ OPTION=1 ./myscript 

e

$ ./myscript 

sarebbe solo essere molto utile.

+0

Credo che la mia domanda sarebbe il motivo per cui si avrebbe bisogno di fare questo? Penserei che ci sia una soluzione migliore. – EBGreen

+6

Di solito non è una domanda utile, @EBGreen. Il fatto che la capacità sia presente nelle shell UNIX suggerisce che è possibile utilizzarlo. In cima alla mia testa: controllare il nome utente e l'indirizzo e-mail che git usa per i commit. Non esiste alcuna opzione da riga di comando per quelli: devi impostarli in ~/.gitconfig, .git/config in ogni repository o envars. Di queste opzioni, gli envars sono chiaramente più facili da impostare al volo (e sovrascrivere comodamente i valori nei file). Quindi se voglio cambiare il mio nome dell'autore per un "git commit" in powershell, come farlo? –

risposta

-3

È possibile impostare le variabili su funzioni e script.

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

New-variabile ha anche un parametro -scope se si vuole essere formale e dichiarare la variabile utilizzando nuova variabile.

+0

Hmmm ... Non pensare che questa risposta si applichi qui. Le variabili di PowerShell non sono variabili d'ambiente. In base alla domanda, il richiedente non sta utilizzando le variabili di ambiente come spazio iniziale (come si farebbe in CMD [se così fosse, questa risposta si applicherebbe]), ma ha bisogno di manipolare l'ambiente prima di richiamare un comando esterno e quindi di ripristinare l'ambiente dopo (o qualcosa in tal senso). – chwarr

16

In genere sarebbe meglio passare informazioni allo script tramite un parametro anziché una variabile globale . Ma se questo è ciò che devi fare e si desidera la pulizia automatica della variabile poi introdurre un nuovo ambito in questo modo:

& { $foo = 'bar'; $env:foo = 'bar'; ./myscript } 

Un paio di cose da notare su questo. Innanzitutto, quando si esce dall'ambito (scriptblock), $ pippo non esiste più. Esisteva solo nel contesto del blocco di script. Tuttavia la variabile d'ambiente $ env: foo esiste ancora perché quello è veramente un cambiamento globale. È possibile eliminare tale variabile in questo modo:

Remove-Item Env:\foo 
+1

Solo un pensiero: non potresti semplicemente generare un nuovo processo di PowerShell, passandoci il blocco di script tramite il parametro -Command? In questo modo non è necessario ripulire l'ambiente in seguito, dal momento che sarà contenuto nel processo figlio. Anche se sto parlando con un MVP PowerShell quindi probabilmente non funziona :-) – Joey

+2

Keith, abbiamo un push-environmentblock e pop-environmentblock in Pscx esattamente per questo scenario ;-) – x0n

+2

Johannes, che funzionerebbe bene ma in qualche modo sembra come barare. :-) PSCX Push/Pop-EnvironmentBlock (l'unico * I * modificato per funzionare in questo modo) funzionerebbe ma non ha il supporto per la pulizia automatica che ha un blocco di script. –

2

per realizzare l'equivalente della sintassi Unix, non è sufficiente impostare la variabile d'ambiente, ma è necessario ripristinare al suo antico valore dopo l'esecuzione del comando. Ho realizzato questo per i comandi più comuni che uso aggiungendo funzioni simili alla seguente al mio profilo PowerShell.

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

Così mycmd è qualche eseguibile che opera in modo diverso a seconda del valore della variabile di ambiente app_master. Definendo cmd_special, ora è possibile eseguire cmd_special dalla riga di comando (inclusi altri parametri) con la variabile di ambiente app_master impostata ... e viene ripristinata (o anche disinserita) dopo l'esecuzione del comando.

Presumibilmente, si potrebbe anche fare questo ad-hoc per una singola chiamata.

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

in realtà dovrebbe essere più facile di questo, ma a quanto pare questo non è un caso d'uso che è facilmente supportato da PowerShell. Forse una versione futura (o una funzione di terze parti) faciliterà questo caso d'uso. Sarebbe bello se PowerShell avesse un cmdlet che farebbe questo, ad es.:

Forse un guru della PowerShell può suggerire come si possa scrivere un tale cmdlet.

0

mi hanno motivato a sufficienza su questo problema che sono andato avanti e ho scritto una sceneggiatura per esso: 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 

D'altra parte, se si installa Gow è possibile utilizzare env.exe che potrebbe essere un po 'più robusto della sceneggiatura veloce che ho scritto sopra.

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 
Problemi correlati