PowerShell: Yalnızca tek bir komut için ortam değişkeni ayarlama


113

Linux'ta şunları yapabilirim:

$ FOO=BAR ./myscript

FOO ortam değişkeni ile "myscript" çağırmak için.

PowerShell'de benzer bir şey mümkün mü, yani önce değişkeni ayarlamak, komutu çağırmak ve sonra değişkeni yeniden ayarlamak zorunda kalmadan?

Kullanım durumum hakkında daha net olmak gerekirse - bunu bir komut dosyasının parçası olarak kullanmak istemiyorum. Bunun yerine, davranışını ortam değişkenlerini kullanarak kontrol edebildiğim, ancak bu durumda komut satırı argümanlarını kullanamadığım bir üçüncü taraf komut dosyam var. Böylece yazarken geçiş yapabilmek

$ OPTION=1 ./myscript

ve

$ ./myscript

sadece çok kullanışlı olurdu.


Sanırım sorum, bunu neden yapmanız gerektiğidir? Daha iyi bir çözüm olduğunu düşünürdüm.
EBGreen

26
Bu genellikle yararlı bir soru değildir, @EBGreen. Yeteneğin UNIX mermilerinde olması gerçeği, bunun bir kullanımı olduğunu gösteriyor. Aklımın ucunda: git'in kaydetme için kullandığı kullanıcı adını ve e-posta adresini kontrol etmek. Bunlar için komut satırı seçeneği yoktur - bunları her depoda ~ / .gitconfig, .git / config veya envars içinde ayarlamanız gerekir. Bu seçeneklerden, envarları anında ayarlamak açıkça daha kolaydır (ve dosyalardaki değerleri uygun şekilde geçersiz kılar). Öyleyse, powershell'de bir "git commit" için yazar ismimi değiştirmek istersem, bunu nasıl yapmalıyım?
Mark Reed

3
Bunun neden gerekli olduğunu sormanın anlamsız olduğuna tamamen katılıyorum. Linux'ta komut satırında çalıştırılırken pancar çorbası kadar yaygındır ve şimdi powershell'den (eğer varsa sözdizimsel bir kabus) acı çekmeye zorlanan bizler sürekli olarak bariz tekniklere cevaplar aramak zorunda kalırız. Önemsiz şeyler yapmak için uzun senaryolar yazmayı saymazsanız, çoğu zaman powershell'de bile bulunmazlar. Beni o kabuktan derinden hayal kırıklığına uğrattığımı say ...
Kim


2
Bağlantı için teşekkürler, @FranklinYu, ancak bu noktada v7.0'dan sonra çok da uzak olmayan bir gelecek sürümde olmasını umuyoruz .
mklement 0

Yanıtlar:


59

Genel olarak, bilgiyi betiğe bir global (ortam) değişkeni yerine bir parametre aracılığıyla geçirmek daha iyi olacaktır. Ancak yapmanız gereken buysa, şu şekilde yapabilirsiniz:

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

Ortam değişkeni $ env: FOO daha sonra şu şekilde silinebilir:

Remove-Item Env:\FOO

2
Sadece bir düşünce: Yeni bir PowerShell işlemi oluşturup, komut dosyası bloğunu -Command parametresi aracılığıyla ona aktaramaz mısınız? Bu şekilde, daha sonra çevreyi temizlemenize gerek kalmaz, çünkü bu çocuk süreçte yer alacaktır. Bir PowerShell MVP ile konuşmama rağmen bu muhtemelen işe yaramıyor :-)
Joey

2
Keith, tam olarak bu senaryo için Pscx'te bir push-environmentblock'umuz ve pop-environmentblock'umuz var ;-)
x0n

2
Johannes, bu da işe yarar ama bir şekilde hile gibi görünüyor. :-) PSCX Push / Pop-EnvironmentBlock (bir ben işi bu şekilde yapmak için değişti) çalışacak ama bir scriptblock sahip olduğunu otomatik temizleme desteği yok.
Keith Tepesi

1
env:fooKaldırmak yerine eski değerine (belki ayarlanmadan) geri dönmeniz gerekmiyor mu?
chwarr

1
@ Joey'in bahsettiği gibi, temiz bir şekilde ortam yapmak istiyorsanız, şunları yapabilirsiniz: & {$pre = $env:foo; $env:foo = 'bar'; ./myscript; if ($pre) {$env:foo = $pre} else {Remove-Item env:\foo}... bazıları beceriksiz diyebilir , ancak yan etkilerden kaçınacaktır ...
Lucas

16

Bu sorun hakkında yeterince motive oldum ve devam edip bunun için bir senaryo yazdım: with-env.ps1

Kullanım:

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

Öte yandan, Gow'u yüklerseniz kullanabilirsiniz.env.exe , yukarıda yazdığım hızlı betiğe göre biraz daha sağlam olanı .

Kullanım:

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

7

Bunu tek bir satırda yapmanın 2 kolay yolu:

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

Bazı nedenlerden dolayı saf tek satırlar içermeyen diğer cevaplardan (teşekkürler millet) özet bilgi.


4

Unix sözdiziminin eşdeğerini başarmak için, yalnızca ortam değişkenini ayarlamanız gerekmez, aynı zamanda komutu çalıştırdıktan sonra onu eski değerine sıfırlamanız gerekir. Bunu, PowerShell profilime aşağıdakine benzer işlevler ekleyerek kullandığım yaygın komutlar için başardım.

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

Yani mycmdortam değişkeninin değerine bağlı olarak farklı çalışır bazı çalıştırılabilir olduğunu app_master. Tanımlayarak cmd_special, artık cmd_specialkomut satırından (diğer parametreler dahil)app_master ortam değişkeni setiyle ... ve komutun çalıştırılmasından sonra sıfırlanır (veya hatta ayarlanamaz).

Muhtemelen, bunu tek bir çağrı için anlık olarak da yapabilirsiniz.

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

Gerçekten bundan daha kolay olmalı, ancak görünüşe göre bu PowerShell tarafından kolayca desteklenen bir kullanım durumu değil. Belki gelecekteki bir sürüm (veya üçüncü taraf işlevi) bu kullanım durumunu kolaylaştıracaktır. PowerShell'in bunu yapacak bir cmdlet'i olması güzel olurdu, örneğin:

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

Belki bir PowerShell gurusu böyle bir cmdlet'in nasıl yazılabileceğini önerebilir.


1

Bunu, komut dosyasını bir İş olarak çalıştırarak yapabilirsiniz :

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

Ayrıca, ArgumentListparametresini kullanarak betiğe argümanlar da iletebilirsiniz Start-Job:

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

Avantajlar ve dezavantajlar

  • Komut dosyası bittikten sonra ortam değişkenini sıfırlamanız gerekmez (bu, try/finally , istisnalar olsa bile bunu doğru şekilde yapmayı ).
  • Ortam değişkeni, başlatılan komut dosyası için gerçekten yerel olacaktır. Muhtemelen paralel olarak başlatılan diğer işleri etkilemeyecektir.
  • Komut dosyası, biraz yalıtılmış bir ortamda çalışacaktır. Bu, başlatılan komut dosyasının ana komut dosyasının değişkenlerini ayarlayamayacağı, ana betiğe Write-Outputgeri iletişim kurmak için kullanması gerektiği anlamına gelir . Bu, kullanım durumuna bağlı olarak bir avantaj veya dezavantaj olabilir.

0

CMD'nin Windows çekirdeğindeki yerel CLI olduğunu (ve hala birçok araç için otomasyon arayüzü olduğunu) göz önünde bulundurarak, PowerShell betiğinizi şu şekilde çalıştırıyor olabilirsiniz: powershell.exe CMD komut isteminden veya CMD konsol ifadelerini kabul eden bir arabirimden .

-FileKomut dosyanızı iletmek için parametreyi kullanıyorsanız, komut powershell.exedosyasının erişmesi için bir ortam değişkeni ayarlamak için başka hiçbir PowerShell kodu kullanılamaz, bu nedenle, bunun yerine ortam değişkenlerinizi CMD ortamında çağırmadan önce ayarlayabilirsiniz powershell.exe:

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

Bir single &da çalışır, ancak komutun devam etmesine izin verir.set herhangi bir nedenle başarısız . (Bu mümkün mü? Hiçbir fikrim yok.)

Ayrıca, "foo=bar"tırnak içine almak daha güvenli olabilir, böylece takip eden hiçbir şey setdeğişken içerik olarak aktarılmaz .


-5

Değişkenleri işlevlere ve komut dosyalarına dahil edebilirsiniz.

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

Biçimsel olmak ve değişkeninizi yeni değişken kullanarak bildirmek istiyorsanız, Yeni Değişken ayrıca bir-kapsam parametresine sahiptir.


1
Hmmm ... Bu cevabın burada geçerli olduğunu düşünmeyin. PowerShell değişkenleri ortam değişkenleri değildir. Soruya göre, soran kişi ortam değişkenlerini çalışma alanı olarak kullanmıyor (CMD'de olduğu gibi [böyle olsaydı, bu cevap geçerli olurdu]), ancak harici bir komutu çağırmadan ve ardından geri yüklemeden önce ortamı değiştirmesi gerekiyor daha sonra çevre (veya bu etkiye yönelik bir şey).
chwarr

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.