Existe uma maneira de executar um comando em vários servidores Windows em paralelo

2

De vez em quando, preciso executar um comando em vários servidores Windows (sincronizar arquivos de um repositório de código-fonte que contém arquivos de script [e outras coisas aleatórias]). O tempo de execução deste comando é dominado pela latência da rede.

Atualmente, eu uso o cmdlet Invoke-Command do PowerShell, mas ele executa o comando sequencialmente em cada host. Como esse script leva um tempo bom para ser executado (às vezes alguns minutos por servidor), eu gostaria de acelerar as coisas executando o comando em paralelo em todos os servidores de uma vez.

Invoke-Command, tanto quanto eu poderia descobrir, não pode fazer isso. O psexec da SysInternals também não pode fazer isso.

Estou vagamente ciente de que o PowerShell tem um recurso de loop paralelo que pode executar várias iterações do loop simultaneamente em vários segmentos. Mas a documentação afirma que isso só está disponível em um fluxo de trabalho do PowerShell, com o qual não estou familiarizado, e parece que isso é um exagero enorme.

Em um shell Unix-y, eu poderia executar cada chamada de psexec em segundo plano. Mas, no meu conhecimento, o PowerShell não suporta isso. Ou eu poderia usar ferramentas como o GNU paralelo ou ts.

Existe uma maneira (simples) de fazer isso em uma máquina com Windows 7?

Se tudo mais falhar, eu poderia escrever um Perl-Script ou algo assim, mas por que reinventar a roda? Certamente não sou a primeira pessoa a encontrar esse problema.

    
por krylon 14.12.2017 / 13:10

1 resposta

5

Você pode usar o Powershell Jobs para executar vários Comandos Invoke em paralelo. Como isso funciona exatamente já foi explicado no Stack Overflow: link

Estou copiando aqui para sua referência, um pouco adaptado ao seu caso de uso:

The Start-Job cmdlet allows you to run code in the background.

foreach ($server in $servers) {
    $running = @(Get-Job | Where-Object { $_.State -eq 'Running' })
    if ($running.Count -le 8) {
        Start-Job {
             $list = Invoke-Command -FilePath .\file.ps1 -ComputerName <hostname>
             ...
        }
    } else {
         $running | Wait-Job
    }
    Get-Job | Receive-Job
}
    
por 14.12.2017 / 13:17