Запуск Powershell-здесь чего-то не хватает

#powershell

Вопрос:

У меня около 20 файлов, каждый из которых содержит IP-адреса. У меня есть функция, которая загружает IP-адреса в правила, которые у меня есть в azure. Сценарий будет работать просто отлично, если запускать его по одному, но мне нужно, чтобы он был параллельным.

 $i=1
foreach ($file in  (gci . -name "auto_farm_protection_*") ){
    Start-Job -ScriptBlock {
        [string[]]$ipsarry = Get-Content $file

        az network nsg rule update -g Testim --nsg-name sg-test -n "test_$i" --source-address-prefix $ipsarry 
            
    } -ArgumentList file,i 

    $i   
}
 

Следует прочитать «test_1» и передать его, «test_2» и передать его и так далее.
По какой-то причине аргументы не передаются в start-job часть, но я их использую -ArgumentsList .

Ответ №1:

Вероятно, это быстрее с помощью start-threadjob из галереи powershell или foreach-object -parallel в powershell 7. Вам также понадобится полный путь к файлам, которые вы открываете, так как, к сожалению, задания используют каталог по умолчанию ~documents (у потоковых заданий этой проблемы нет). Я дважды процитировал команду az в качестве демонстрации, так как у меня ее нет.

 # echo 192.168.1.1 > auto_farm_protection_a
# echo 192.168.1.2 > auto_farm_protection_b
# Install-Module -Name ThreadJob

$i=1
$result = foreach ($file in (gci . "auto_farm_protection_*") ){
    Start-ThreadJob -ScriptBlock {
        param($file, $i)
        [string[]]$ipsarry = Get-Content $file.fullname
        "az network nsg rule update -g Testim --nsg-name sg-test -n test_$i --source-address-prefix $ipsarry"
    } -Argumentlist $file,$i 
    $i   
}
$result | receive-job -wait -autoremove


az network nsg rule update -g Testim --nsg-name sg-test -n test_1 --source-address-prefix 192.168.1.1
az network nsg rule update -g Testim --nsg-name sg-test -n test_2 --source-address-prefix 192.168.1.2
 

Комментарии:

1. Большое спасибо

Ответ №2:

В вашем коде есть две ошибки. Первый из них находится в:

 -ArgumentList file,i
 

Вы передаете литеральные строки «файл» и «я» в качестве аргументов, так как вы отсутствуете $ перед именами переменных.

Во-вторых, вы ссылаетесь на аргументы по имени из блока сценария, не объявив именованные параметры. Это можно исправить, добавив param( $file, $i ) строку в блок сценария.

Полное исправление:

 $i=1
foreach ($file in  (gci . -name "auto_farm_protection_*") ){
    Start-Job -ScriptBlock {
        param( $file, $i )

        [string[]]$ipsarry = Get-Content $file.FullName

        az network nsg rule update -g Testim --nsg-name sg-test -n "test_$i" --source-address-prefix $ipsarry 
            
    } -ArgumentList $file, $i 

    $i   
}
 

Как вы заметили, модификатор области «использование:» намного проще в использовании, так как он делает параметры устаревшими:

 $i=1
foreach ($file in  (gci . -name "auto_farm_protection_*") ){
    Start-Job -ScriptBlock {
        [string[]]$ipsarry = Get-Content $using:file.FullName

        az network nsg rule update -g Testim --nsg-name sg-test -n "test_$using:i" --source-address-prefix $ipsarry 
            
    }

    $i   
}
 

Комментарии:

1. для получения содержимого потребуется файл$. полное имя тоже, так как каталог заданий по умолчанию ~documents.

2. @js2010 Не требуется, так как Get-Content автоматически считывает FullName поле при FileInfo передаче объекта.

3. gci -имя передает только строку.

4. @js2010 На самом деле приведенный выше код работает в ядре PS 7, но не работает в PS 5. См. Проблему с GitHub . Так что я добавлю .FullName на всякий случай.

5. get-content -путь преобразуется в строки. Странно, что он получает полный путь в powershell 5.1 в заданиях. get-childitem-name вернет только строку, а не объект fileinfo.

Ответ №3:

По какой-то причине пришлось использовать $using:varname

Комментарии:

1. Блок сценариев Start-Job выполняется в своей собственной удаленной области. Эта область ничего не знает о вызывающей области, в которой $i она определена.