Как работает концепция конвейера PowerShell?

Я понимаю, что конвейер PowerShell работает, принимая выходные данные одного командлета и передавая его другому командлету в качестве входных данных. Но как это происходит?

завершает ли первый командлет, а затем передает все выходные переменные сразу, которые затем обрабатываются следующим командлетом?

или каждый вывод из первого командлета выполняется по одному, а затем выполняется через все остальные командлеты конвейера?

3 ответов


вы можете увидеть, как порядок конвейера работает с простым битом скрипта:

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

выходы:

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

труба Powershell работает асинхронно. Это означает, что вывод первого командлета доступен второму командлету сразу один объект в то время (даже если первый не закончил выполнение).

например, если вы запустите следующую строку:

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

а затем остановить выполнение, нажав Control+C вы увидите часть каталога записывается в текстовый файл.

лучшим примером является следующий код:(это действительно полезно удалить все .tmp файлы на диске c:)

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

каждый раз, когда $_ во втором командлете получает значение (одного файла)


оба ответа thusfar дают вам хорошую информацию о конвейерной связи. Однако можно сказать и больше.

во-первых, чтобы напрямую ответить на ваш вопрос, Вы указали два возможных способа работы конвейера. И оба они правы... в зависимости от командлетов по обе стороны трубы! Однако, путь трубопровода должны работа ближе к вашему второму понятия: объекты обрабатываются по одному за раз. (Хотя нет никакой гарантии, что объект пойдет на все путь до начала следующего, потому что каждый компонент в конвейере является асинхронным, как упоминал S Nash.)

Итак, что я имею в виду под "это зависит от ваших командлетов" ? Если вы говорите о командлетах, поставляемых Microsoft, они, вероятно, все работают так, как вы ожидаете, передавая каждый объект через конвейер так эффективно, как он может. Но если вы говорите о командлетах, которые вы пишете, это зависит от того, как вы их пишете: так же легко писать командлеты, которые не могут этого сделать правильный pipelining как те которые преуспевают!

существует два основных режима отказа:

  • генерация всех выходных данных перед излучением в трубопровод, или
  • сбор всех входных данных трубопровода перед обработкой.

то, к чему вы хотите стремиться, - это, конечно, обрабатывать каждый вход, как только он получен, и испускать его выход, как только он определен. Для подробных примеров всего этого см. мою статью,Ins и Выходы конвейера PowerShell, только что опубликовано на Simple-Talk.com.