Rrunning the script on remote computers one by one

Good afternoon, I need to run a script on remote computers one by one, at first the script should be executed only on the first computer and only after completion it should be executed on the second. The fact is that this is a cluster of servers, the servers provide for restarting services, they need to be started in a certain sequence.

@BigSmoke Welcome to PowerShell.org forums.

Do you have any code already ? if yes please share it here by removing any sensitive data from it, Otherwise try reading Invoke-Command this and checkout the examples shown there. It will help.

1 Like

@kvprasoon here is my sample code. I plan to run the script on 4 servers, the service can be stopped and the folders are cleaned at the same time, but the services must be started in a clear sequence, the first server starts the service after all specified folders are cleaned up. after that, when the service status on the first server is “running”, you can start the service on the second server. when the service status on the second server is “running”, you can start the service on the third server.
If I use Invoke-Command, the script will fly to 4 servers and execute there, and there will be no sequential start of services on the servers.

$services1C = Get-WmiObject win32_service | ? { $_.Name -like '*' } |
Select Name, DisplayName, State, PathName | 
Where-Object { $_.PathName -Like "*pdf24.exe*" };
$Date = Get-Date -Format dd-MM-yyyy-hh-mm

Start-Transcript -Path C:\temp\Сleaning1С_$Date.txt

# Stopping the service
$services1C | % {
    $serviceInfo = $_
    $serviceName = $serviceInfo.Name

    # 1.Stop the pdf24 service
    Write-Host "Stopping the service: $serviceName" -ForegroundColor yellow
    Stop-Service -Name $serviceName -NoWait
    #$svc.WaitForStatus('Stopped')
    Write-Host "Pause for 10 seconds" -foregroundColor yellow
    Start-Sleep 10
    $svc = Get-Service $serviceName
    Write-Host "service $serviceName "$svc.Status""

};

# Stopping processes
$Error.Clear()
        Stop-Process -Name ragent -Force -ErrorAction SilentlyContinue
        if($Error -like "*pdf24*")
            {
                Write-Host "No pdf24 processes running" -ForegroundColor Green
            }
            else{
                Write-Host "All pdf24 processes terminated" -ForegroundColor DarkGreen
            };

    Write-Host "Pause for 10 seconds" -foregroundColor yellow
    Start-Sleep 10

        # 1. Clearing the data
        Write-Host 'We clear the directory: "C:\temp\tmp_out34\"' -ForegroundColor yellow
        Remove-item -Path "C:\temp\tmp_out34\*" -Force -Recurse
        
            $services1C | % {
                $serviceInfo = $_
                $serviceName = $serviceInfo.Name

        # 1. We start the service pdf24
            $a = Get-ChildItem -Path "\\my-PC\c$\temp\tmp_out34" -Recurse
            $b = Get-ChildItem -Path "\\my-PC\c$\temp\logs" -Recurse
            
            if(($a.Count -eq 0) -and ($b.Count -eq 0))
            {
                Start-Service -Name $serviceName
                $svc = Get-Service $serviceName
                Write-Host "Service start: $serviceName" -ForegroundColor yellow
                Write-Host "Service $serviceName "$svc.Status""
            }
            else{
                Write-Host "The folder is not empty" -ForegroundColor DarkGreen
            };
                
                
                #$svc.WaitForStatus('Running')
                
            }
Stop-Transcript

You will have to do it in two different invokes in this case. One for stopping and another for starting. You can keep the server names in an array in the required sequence.

@kvprasoon tell me how to do it right please? The two different calls are understandable, but why wait for the second call to start the task, to start the services. And if servers are specified in the array, will they be executed in turn, or do you still need to write 4 tasks to call the server by the array index?

You can create two scriptblocks.

1. For stopping and cleaning up.

$ServiceStopScriptBlock = {
   # What ever cleaning code
}

2. For starting and waiting.

$ServiceStartScriptBlock = {
   # What ever start and wait code
}

3. Then have an array of computers

# In the order you want the service start to happen
$ServerList = @('Server1', 'Server2', 'Server3') 

4. Create PS sessions as there will be more than one call for each server.

$SessionList = $ServerList | Foreach-Object -Process  { New-PSSession -ComputerName $_ }

5. Stop services

Invoke-Command -Session $SessionList -ScriptBlock $ServiceStopScriptBlock

6. Start services

# This will go in order
$SessionList | Foreach-Object -Process {
   Invoke-Command -Session $_ -ScriptBlock $ServiceStartScriptBlock
}

PS. Just a sample flow.

@kvprasoon in the end I got the following code, tried it on one test server, it seems to work. Was it supposed to look like this or did I do something wrong? Will it wait for the stop block to execute before starting the start block?


$ServiceStopScriptBlock = {
# Stopping the Service
$services1C = Get-WmiObject win32_service | ? { $_.Name -like '*' } |
Select Name, DisplayName, State, PathName | 
Where-Object { $_.PathName -Like "*ragent.exe*" };

$services1C | % {
    $serviceInfo = $_
    $serviceName = $serviceInfo.Name

    # 1. Stop the 1С service
    Write-Host "Stopping the service: $serviceName" -ForegroundColor yellow
    Stop-Service -Name $serviceName -NoWait -Force
    #$svc.WaitForStatus('Stopped')
    Write-Host "Pause for 10 seconds" -foregroundColor yellow
    Start-Sleep 10
    $svc = Get-Service $serviceName
    Write-Host "service $serviceName "$svc.Status""

};

# Stopping processes
$Error.Clear()
        

    Stop-Process -Name ragent -Force -ErrorAction SilentlyContinue
        if($Error -like "*ragent*")
            {
                Write-Host "not ragent processes running" -ForegroundColor Green
            }
            else{
                Write-Host "all ragent processes terminated" -ForegroundColor DarkGreen
            }

    Stop-Process -Name rmngr -Force -ErrorAction SilentlyContinue
        if($Error -like "*rmngr*")
            {
                Write-Host "not rmngr processes running" -ForegroundColor Green
            }
            else{
                Write-Host "all rmngr processes terminated" -ForegroundColor DarkGreen
            }
    Stop-Process -Name rphost -Force -ErrorAction SilentlyContinue
        if($Error -like "*rphost*")
            {
                Write-Host "not rphost processes running" -ForegroundColor Green
            }
            else{
                Write-Host "all rphost processes terminated" -ForegroundColor DarkGreen
            };
            
    Write-Host "Pause for 10 seconds" -foregroundColor yellow
    Start-Sleep 10

# 1. Clearning the data
        
        Write-Host 'we clear the directory: "C:\Users\srv\AppData\Local\1C\1cv8\"' -ForegroundColor yellow
        Remove-item -Path "C:\Users\srv\AppData\Local\1C\1cv8\*" -Force -Recurse
        
        Write-Host 'we clear the directory: "C:\Users\srv\AppData\Local\Temp\"' -ForegroundColor yellow
        Remove-item -Path "C:\Users\srv\AppData\Local\Temp\*" -Force -Recurse

        Write-Host 'we clear the directory: "C:\Users\srv\AppData\Roaming\1C\1cv8\"' -ForegroundColor yellow
        Remove-item -Path "C:\Users\srv\AppData\Roaming\1C\1cv8\*" -Force -Recurse

        Write-Host 'we clear the directory: "C:\Program Files\1cv8\srvinfo\reg_1541\snccntxce2f2eac-1568-4f5d-8ead-be4e9764395f"' -ForegroundColor yellow
        Remove-item -Path "C:\Program Files\1cv8\srvinfo\reg_1541\snccntxce2f2eac-1568-4f5d-8ead-be4e9764395f\*" -Force -Recurse -ErrorAction SilentlyContinue
}

$ServiceStartScriptBlock = {
$services1C = Get-WmiObject win32_service | ? { $_.Name -like '*' } |
Select Name, DisplayName, State, PathName | 
Where-Object { $_.PathName -Like "*ragent.exe*" };
        
            $services1C | % {
                $serviceInfo = $_
                $serviceName = $serviceInfo.Name

        # 1. We start the service 1С
            $a = Get-ChildItem -Path "C:\Users\srv\AppData\Local\1C\1cv8\" -Recurse
            $b = Get-ChildItem -Path "C:\Users\srv\AppData\Local\Temp\" -Recurse
            $c = Get-ChildItem -Path "C:\Users\srv\AppData\Roaming\1C\1cv8\" -Recurse
            
            if(($a.Count -eq 0) -and ($b.Count -eq 0) -and ($c.Count -eq 0))
            {
                Start-Service -Name $serviceName
                $svc = Get-Service $serviceName
                Write-Host "Start service: $serviceName" -ForegroundColor yellow
                Write-Host "Service $serviceName "$svc.Status""
            }
            else{
                Write-Host "The folder is not empty" -ForegroundColor DarkGreen
            };
            }
}

$ServerList = @('Server.lan')
$SessionList = $ServerList | Foreach-Object -Process  { New-PSSession -ComputerName $_ }
Invoke-Command -Session $SessionList -ScriptBlock $ServiceStopScriptBlock
$SessionList | Foreach-Object -Process {
   Invoke-Command -Session $_ -ScriptBlock $ServiceStartScriptBlock
}