2

We have a few servers (Windows Server 2012 R2) in our environment that install updates automatically and restart after that.

After the restart we would like to check the status of all the (Windows) services which are set to automatic start. If a service did not start, the script would try to start the service 3 times and if all attempts fail, it should send an email notification so that we can check what's wrong with this service on this server.

I was wondering if there already existed an easy solution, maybe a PowerShell script?

Peter
  • 27

4 Answers4

1

I would advise you to look into getting a NMS. We use PRTG and it works well. In it you can create sensors that monitors windows services using WMI. You can configure the sensor to send mail/start scripts if the service go down.

PRTG is licensed by sensors, but the free version gives you 100, which should be enough for a couple of servers (You need one sensor per service to monitor)

1

Powershell would be a great way to monitor these services. Oddly enough, I was just reading a blog about this today. I will try to link the script if I can find it, but the general gist of it would be:

1.) Find services that are set to start automatically.

2.) Check the state of the service.

The trick is that the

get-service

cmdlet does not output any sort of 'StartupType', so you will have to use the Win32_Service WMI object instead.

Foreach($Server in $ServerList){
    Get-WmiObject -ComputerName $Server Win32_Service | 
    Where-Object {$_.StartMode -eq 'Auto' -AND $_.State -eq 'Stopped'}
}

This should get you a list of services fitting your desired parameters.

NOTES There are a couple of notes to this:

1.) I would highly recommend you have this script start a couple of minutes after the servers start up as the $_.StartMode -eq 'Auto' will encompass services set to start immediately after booting AND ones set to start automatically after a delay.

2.) There will be services that will be returned through this one-liner that you probably do not care about monitoring. (I.E. on my laptop, a service called "TrustedInstaller" fit this criteria and was returned as a stopped service :/ ) So you would most likely need to filter out these as well.

1

Service > Properties > Recovery

enter image description here

Can select what to do on first 3 failures, including restarting service or running a command.

This is where you would also use Run program to set your script that would restart service, clear a file, send you a notification, etc. I am all for NMS (Zabbix) or Powershell script, but most of this can be solved natively and GPO (if applicable to your environment) can have this set across all necessary services/machines.

Jon Conley
  • 328
  • 1
  • 7
0

I found a Powershell script that is perfect for me, I just need to customize it a bit. Here is the link http://doitcloudy.blogspot.de/2014/07/scriptgesteuerter-neustart-von-windows.html (German, but the script on the bottom of the page is all English). However, I need some help with this part (lines 130 and following):

foreach ($item in $report){
Write-Host "Starting Service " $item.Name " on server: " $item.Server -Foregroundcolor yellow
$start = Get-Date
$startSVCblock = {param($item) Start-Service -InputObject (Get-Service -ComputerName $item.Server -Name $item.Name)}
$j = Start-Job -ScriptBlock $startSVCblock -Arg $item
do {
    if ($j.State -ne 'Running') { break} 
    $j | Receive-Job
} while (((Get-Date) - $start) -le $timeout)

}

I see that this is the part where the script starts a service, but I'm not used to jobs in Powershell. How should I edit the script so that when starting the service fails, it writes the service name to a log file? Maybe with try/catch?

Edit:

If anyone stumbles upon this and wants to know how I solved it: After a lot of research I found out that it is extremely difficult to write the output of Receive-Job to a log file. So I chose a different approach: I check if the server is running after the job has finished. Here's the code:

foreach ($item in $report){
Write-Output "Starting Service " $item.Name " on server: " $item.Server
$start = Get-Date
$startSVCblock = {param($item) Start-Service -InputObject (Get-Service -ComputerName $item.Server -Name $item.Name)}
$j = Start-Job -ScriptBlock $startSVCblock -Arg $item
do {
    if ($j.State -ne 'Running') { break} 
    $j | Receive-Job
} while (((Get-Date) - $start) -le $timeout)
$newService = Get-Service -ComputerName $item.Server -Name $item.Name
if ($newService.Status -ne "Running") { LogWrite "$item could not start" }

}
Peter
  • 27