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

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

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

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


person Richard    schedule 26.06.2013    source источник


Ответы (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
person Keith Hill    schedule 26.06.2013

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

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

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

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

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

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

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

person S Nash    schedule 26.06.2013

Оба ответа до сих пор дают вам полезную информацию о конвейерной обработке. Однако есть еще что сказать.

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

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

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

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

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

person Michael Sorens    schedule 07.11.2015