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 contendo 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 bom tempo para ser executado (algumas vezes por alguns minutos por servidor), eu gostaria de acelerar as coisas executando o comando em paralelo em todos os servidores ao mesmo tempo.

Invoke-Command, tanto quanto pude 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 threads. 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, que eu saiba, o PowerShell não suporta isso. Ou eu poderia usar ferramentas como 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 enfrentar esse problema.

krylon
fonte
O GNU Parallel usa como padrão o SSH, portanto, a menos que você queira executar outra ferramenta para conectar-se, precisará executar um serviço ssh nos servidores.
Ole Tange

Respostas:

5

Você pode usar os trabalhos do Powershell para executar vários comandos de chamada em paralelo. Como isso funciona exatamente já foi explicado no Stack Overflow: https://stackoverflow.com/questions/8781666/run-n-parallel-jobs-in-powershell

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

O cmdlet Start-Job permite executar o código em segundo plano.

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
}
hanjo
fonte