2013-06-26 14 views
8

Rozumiem, że przewody PowerShell działają, pobierając dane wyjściowe jednego cmdletu i przekazując je do innego polecenia cmdlet jako dane wejściowe. Ale w jaki sposób to robi?Jak działa koncepcja potoku PowerShell?

Czy pierwsze cmdlet kończy się, a następnie przekazuje wszystkie zmienne wyjściowe na raz, które są następnie przetwarzane przez następne polecenie cmdlet?

Czy każde wyjście z pierwszego cmdletu jest wykonywane pojedynczo, a następnie jest uruchamiane przez wszystkie pozostałe polecenia cmdlet?

Odpowiedz

10

można zobaczyć jak rozkaz rurociąg pracuje z prostego kawałka skryptu:

function a {begin {Write-Host 'begin a'} process {Write-Host "process a: $_"; $_} end {Write-Host 'end a'}} 
function b {begin {Write-Host 'begin b'} process {Write-Host "process b: $_"; $_} end {Write-Host 'end b'}} 
function c { Write-Host 'c' } 

1..3 | a | b | c 

Wyjścia:

begin a 
begin b 
process a: 1 
process b: 1 
process a: 2 
process b: 2 
process a: 3 
process b: 3 
end a 
end b 
c 
5

Rura Powershell działa w sposób asynchroniczny. Oznacza to, że dane wyjściowe pierwszego polecenia cmdlet są dostępne dla drugiego polecenia cmdlet natychmiast po jednym obiekcie (nawet jeśli pierwszy nie został zakończony).

Na przykład, jeśli uruchomić poniższy wiersz:

dir -recurse| out-file C:\a.txt 

a następnie zatrzymać wykonywanie wciskając Ctrl + C będzie można zobaczyć część katalogu są zapisywane w pliku tekstowym.

Lepszym przykładem jest następujący kod: (co jest rzeczywiście przydatne, aby usunąć wszystkie pliki .tmp na dysku C :)

get-childitem c:\ -include *.tmp -recurse | foreach ($_) {remove-item $_.fullname} 

każdym razem $ _ w drugim cmdletu dostaje wartość (pojedynczy plik)

1

Obie odpowiedzi w ten sposób dają dobre informacje na temat potokowania. Jednak jest jeszcze coś do powiedzenia.

Po pierwsze, aby bezpośrednio odpowiedzieć na twoje pytanie, przewidziano dwa możliwe sposoby działania potoku. Oboje mają rację ... w zależności od cmdletów po obu stronach rury! Jednak sposób, w jaki potok powinien działać, jest bliższy Twojemu drugiemu poglądowi: obiekty są przetwarzane pojedynczo. (Chociaż nie ma gwarancji, że obiekt przejdzie przez całą drogę przed następnym uruchomieniem, ponieważ każdy komponent w potoku jest asynchroniczny, jak wspomniał S Nash.)

Co mam na myśli przez "to zależy od twojego cmdlet "? Jeśli mówisz o cmdletach dostarczanych przez Microsoft, prawdopodobnie wszystkie działają tak, jak byś tego oczekiwał, przekazując każdy obiekt przez potok tak skutecznie, jak to tylko możliwe. Ale jeśli mówisz o poleceniach cmdlet, które piszesz, to zależy od tego, jak je piszesz: równie łatwo można pisać polecenia cmdlet, które nie wykonują poprawnego pipeliningu jako te, które się powiodły!

Istnieją dwa zasadnicze rodzaje awarii:

  • generujące wszystkie wyjścia przed emitujących każdy do rurociągu lub
  • zbierając wszystkie wejścia rurociągu przed przetworzeniem dowolny.

To, co chcesz osiągnąć, to przetwarzanie każdego wejścia zaraz po jego otrzymaniu i emisję sygnału wyjściowego, gdy tylko zostanie to określone.Szczegółowe przykłady wszystkich z nich można znaleźć w moim artykule, Ins and Outs of the PowerShell Pipeline, opublikowanym na stronie Simple-Talk.com.