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.
@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
}