Run Powershell commands on many systems

run powershell commands on many systems

One of the best things about powershell is the ability to run commands on many systems at once or in a loop. There are a few ways to do this and I’ll go over a few of my favorite in this post. First, We need to get an array filled with the systems that we want to work on.

Fill Array with Systems

This will be used in each of our methods for running commands on systems. Here is how the code looks:

# initialize the array
$systems = @()

$systems = (
     "System1",
     "System2",
     "System3"
)

Multiple PSSessions

First up is the simplest we will use New-PSSession and Invoke-Command. Since we already have our array of systems here is how you create the PSSession to ALL of the systems at once:

#Check for Creds and ask for them if they aren't found
if (!($Creds)) {$creds = get-credential -Message "Enter your Admin Creds"}

# Create PSSessions to all the systems in the array
$sessions = New-PSSession -ComputerName $systems -Credential $Creds

Now that we have our sessions we can run whatever commands we want using invoke-command. Here is an example of running gpupdate on all the systems at once. Whatever you put inside the curly brackets is what will be run on each system. For ease knowing the the heck happened I always put the hostname command first. This just prints the hostname right before the results of the second commands so you can tell if the command worked on each system. You can string multiple commands together with the semi-colon (;).

Invoke-Command -Session $sessions -ScriptBlock {hostname;gpupdate /force /boot}

Foreach loop

Depending on the command you are running maybe you don’t want all the systems to run the command at the same time. You can accomplish this with a foreach loop. We will still use invoke-command, but the commands will run one system at a time. We will run the same gpupdate command. Here is how that code looks:

foreach ($system in $systems){
     Invoke-Command -Computername $system -ScriptBlock {hostname; gpupdate /force /boot}
}

Foreach-Object loop (PS 7+ only)

Starting in Powershell 7 we have a new way to run for loops. We can run them in a mode called parallel. Instead of the old school for loop that runs one iteration at a time, it will run multiple iterations at once. You can even throttle it to say run 2 or three at once. This is my favorite loop type for sure. I mention the throttle because depending on the command you are trying to run if you have too many threads running at once its actually slower than a traditional for loop. Crazy right? You will see it as you use it more, but for the most part you can let it rip and its waaay faster than waiting on a regular loop. Here is how it looks with the same command we have been using:

$systems | ForEach-Object -Parallel  {
     Invoke-Command -Computername $_ -ScriptBlock {hostname; gpupdate /force /boot}
}

Notice that we use the $_ for the computer name. This is how you access the array one item at a time in this type of loop.

Tagged :