Home > Mobile >  Powershell running invoke-command on several servers using -Asjob but log completion log locally
Powershell running invoke-command on several servers using -Asjob but log completion log locally

Time:05-05

I am trying to run a powershell script that installs some software on a bunch of remote servers. I am using the -Asjob option to run them synchronously. I'm also using for loop to run the remote commands on each server, but i want to write a "Done" log file locally where i am running the script to notify me exactly when each server completes the commands.

This is the sample code i am testing, and the script runs fine, but the "Done" log files gets generated immediately, and not as each server finishes.

$VerbosePreference = 'Continue'
$servers = Get-Content -Path f:\temp\servers.txt

foreach($server in $servers) {
    Write-Verbose "Start batch file as a job on $server"
    Start-Sleep -Seconds 3
    Invoke-Command -ComputerName $server -ScriptBlock {
    echo testfile1 > f:\temp\testfile1.txt
    Start-Sleep -Seconds 20
    echo testfile2 > f:\temp\testfile2.txt
    Start-Sleep -Seconds 20
    echo testfile3 > f:\temp\testfile3.txt
    echo DONE} > f:\temp\$server.done.txt -Asjob
} 

thanks

CodePudding user response:

Remove the redirection operator after Invoke-Command { ... } - otherwise you'll be redirecting the resulting job objects to file, rather than the output from the jobs - instead, collect all the job objects to a variable $jobs:

$VerbosePreference = 'Continue'
$servers = Get-Content -Path f:\temp\servers.txt

$jobs = foreach($server in $servers) {
    Write-Verbose "Start batch file as a job on $server"
    Start-Sleep -Seconds 3
    Invoke-Command -ComputerName $server -ScriptBlock {
    echo testfile1 > f:\temp\testfile1.txt
    Start-Sleep -Seconds 20
    echo testfile2 > f:\temp\testfile2.txt
    Start-Sleep -Seconds 20
    echo testfile3 > f:\temp\testfile3.txt
    echo DONE} -Asjob
}

Now that we've kicked off all the remoting jobs and collected the pertaining job object, we simply need to wait and then collect the output:

foreach($job in $jobs){
    # Wait for jobs to finish, retrieve their output
    $jobOutput = $job |Receive-Job -Wait 

    # Grab the remote server name from the output
    $server = $jobOutput |ForEach-Object PSComputerName |Select -First 1

    # Write output to file
    $jobOutput > f:\temp\$server.done.txt
}
  • Related