Gibt es eine Möglichkeit, einen Befehl auf mehreren Windows-Servern gleichzeitig auszuführen?

2

Hin und wieder muss ich einen Befehl auf mehreren Windows-Servern ausführen (Dateien aus einem Quellcode-Repository synchronisieren, das Skriptdateien [und andere zufällige Dinge] enthält). Die Ausführungszeit dieses Befehls wird von der Netzwerklatenz bestimmt.

Derzeit verwende ich das PowerShell-Cmdlet "Invoke-Command", das den Befehl jedoch nacheinander auf jedem Host ausführt. Da die Ausführung dieses Skripts viel Zeit in Anspruch nimmt (manchmal einige Minuten pro Server), möchte ich die Ausführung des Befehls auf allen Servern gleichzeitig beschleunigen.

Invoke-Command kann das, soweit ich das beurteilen kann, nicht. SysInternals 'psexec kann das auch nicht.

Ich bin mir vage bewusst, dass PowerShell über eine parallele Schleifenfunktion verfügt, die mehrere Iterationen der Schleife gleichzeitig auf mehreren Threads ausführen kann. In der Dokumentation heißt es jedoch, dass dies nur in einem PowerShell-Workflow verfügbar ist, mit dem ich nicht vertraut bin, und es klingt nach einem massiven Overkill.

In einer Unix-y-Shell konnte ich jeden Aufruf von psexec im Hintergrund ausführen. Meines Wissens unterstützt PowerShell dies jedoch nicht. Oder ich könnte ein Tool wie GNU parallel oder ts verwenden.

Gibt es eine (einfache) Möglichkeit, dies auf einem Windows 7-Computer zu tun?

Wenn alles andere fehlschlägt, könnte ich ein Perl-Skript schreiben oder so, aber warum das Rad neu erfinden? Ich bin sicherlich nicht der erste, der auf dieses Problem stößt.

krylon
quelle
GNU Parallel verwendet standardmäßig SSH. Wenn Sie also nicht möchten, dass es ein anderes Tool zum Herstellen einer Verbindung ausführt, müssen Sie einen ssh-Dienst auf den Servern ausführen.
Ole Tange

Antworten:

5

Sie können Powershell-Jobs verwenden, um mehrere Aufrufbefehle gleichzeitig auszuführen. Wie das genau funktioniert, wurde bereits bei Stack Overflow erklärt: https://stackoverflow.com/questions/8781666/run-n-parallel-jobs-in-powershell

Ich kopiere es hier als Referenz, leicht an Ihren Anwendungsfall angepasst:

Mit dem Cmdlet Start-Job können Sie Code im Hintergrund ausführen.

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
quelle