[Xymon] PS client enhancement of ServiceCheck

Timothy Williams tlwilliams4 at vcu.edu
Mon Oct 8 18:05:59 CEST 2018


All, I've started using the servicecheck function to restart services more
extensively lately. However, I encountered a department which needs to shut
down a monitored service during a maintenance window, and the servicecheck
would restart it. Thus, I created a 'noservicecheck' item in the
client-local.cfg process. Hope you find it useful enough to add to next PS
version.

Tim Williams
Virginia Commonwealth University Computing Center

Here is a section to add to the XymonPSClient.doc help file:
noservicecheck

noservicecheck:SERVICENAME:DAYOFWEEK:STARTHOUR:DURATION

Checks if a specified Windows Service servicecheck exists and suppresses it
during the specified Maintenance Window. Window can span multiple days, as
specified by Duration, but would terminate if script is restarted after
initiation day/hour.

SERVICENAME – name of the service to check for a ‘servicecheck’ statement.

DAYOFWEEK – numeric day of the week, where Sunday = 0, Monday = 1, etc.

STARTHOUR – military hour to start the Maintenance Window, 0 for midnight
up to 23

DURATION – how long in hours a servicecheck should not institute a restart

Examples:

servicecheck:Sophos Message Router:10

noservicecheck:Sophos Message Router:0:5:1

(no restart starting first scan after Sunday 5AM to first scan after 6AM)
*Here are the revisions in XymonClient.PS1:*

*Add* following to declared variables about line 48:
     $MaintChecks = @{}

*Add* line to function XymonClientConfig($cfglines) for new item to be
recognized:
    -or $l -match '^noservicecheck:' `

*Replace* 'servicecheck' function:

function XymonServiceCheck
{
    WriteLog "Executing XymonServiceCheck"
    if ($script:clientlocalcfg_entries -ne $null)
    {
       $servicecfgs = @($script:clientlocalcfg_entries.keys | where { $_
-match '^servicecheck' })
            foreach ($service in $servicecfgs)
            {
                # parameter should be
'servicecheck:<servicename>:<duration>'
                $checkparams = $service -split ':'
                # validation
                if ($checkparams.length -ne 3)
                {
                    WriteLog "ERROR: not enough parameters (should be
servicecheck:<servicename>:<duration>) - $checkparams[1]"
                    continue
                }
                else
                {
                    $duration = $checkparams[2] -as [int]
                    if ($checkparams[1] -eq '' -or $duration -eq $null)
                    {
                        WriteLog "ERROR: config error (should be
servicecheck:<servicename>:<duration>) - $checkparams[1]"
                        continue
                    }
                }
                # check for maintenance window
                  $serviceexclds = @($script:clientlocalcfg_entries.keys |
where { $_ -match '^noservicecheck' })
                    foreach ($maintservice in $serviceexclds)
                    {
                    # parameter should be
'noservicecheck:<servicename>:<numeric day of week Sun=0>:<military start
hour>:<duration in Hours>'
                  $checkMparams = $maintservice -split ':'
                  if ($checkparams[1] -eq $checkMparams[1]){
                     # validation of number of parameters
                    if ($checkMparams.length -ne 5)
                    {
                        WriteLog ("ERROR: not enough parameters
(noservicecheck:<servicename>:<numeric day of week Sun=0>:<military start
hour>:<duration Hrs> {0}" -f $checkMparams[1])
                        continue
                    }
                    else
                    {
                    # get values
                        $MaintDay = $checkMparams[2] -as [int]
                            if($MaintDay -eq 0){$MaintWeekDay = "Sunday"}
                            if($MaintDay -eq 1){$MaintWeekDay = "Monday"}
                            if($MaintDay -eq 2){$MaintWeekDay = "Tuesday"}
                            if($MaintDay -eq 3){$MaintWeekDay = "Wednesday"}
                            if($MaintDay -eq 4){$MaintWeekDay = "Thursday"}
                            if($MaintDay -eq 5){$MaintWeekDay = "Friday"}
                            if($MaintDay -eq 6){$MaintWeekDay = "Saturday"}
                        $MaintStartHour = $checkMparams[3] -as [int]
                        $MaintDuration = $checkMparams[4] -as [int]
                    # validation of basic values
                        if ($checkMparams[1] -eq '' -or $MaintDuration -eq
$null -or ($MaintDay -inotin 0..6) -or ($MaintStartHour -inotin 0..23))
                        {
                            WriteLog ("ERROR: config error
(noservicecheck:<servicename>:<numeric day of week Sun=0>:<military start
hour>:<duration Hrs>) {0}" -f $checkMparams[1])
                            continue
                        }
                    }

                        if (((get-date).DayofWeek -eq $MaintWeekDay) -and
((get-date).Hour -eq $MaintStartHour) ) {
                            if
($script:MaintChecks.ContainsKey($checkMparams[1])) {
                                $MaintWindowEnd =
$script:MaintChecks[$checkMparams[1]].AddHours($MaintDuration)
                                if ((get-date) -lt $MaintWindowEnd){
                                    WriteLog (" Maintenance: Skipping
Service Check until after $($MaintWindowEnd) for {0}" -f $checkMparams[1])
                                    continue
                                }Else{
                                clear.variable $script:MaintChecks
                                }
                            }
                            else{
                             WriteLog ("Not seen this NoServiceCheck
before, starting Maintenance Window now for {0}" -f $checkMparams[1])
                             $hourTop = (get-date).Minute
                             $script:MaintChecks[$checkMparams[1]] =
(get-date).AddMinutes(-($hourTop))
                             continue
                            }
                         }
                    # end of maintenance hold
                }
                WriteLog ("Checking service {0}" -f $checkparams[1])

                $winsrv = Get-Service -Name $checkparams[1]
                if ($winsrv.Status -eq 'Stopped')
                {
                    writeLog ("!! Service {0} is stopped" -f
$checkparams[1])
                    if ($script:ServiceChecks.ContainsKey($checkparams[1]))
                    {
                        $restarttime =
$script:ServiceChecks[$checkparams[1]].AddSeconds($duration)
                        writeLog "Seen this service before; restart time is
$restarttime"
                        if ($restarttime -lt (get-date))
                        {
                            writeLog (" -> Starting service {0}" -f
$checkparams[1])
                            $winsrv.Start()
                        }
                    }
                    else
                    {
                        writeLog "Not seen this service before, setting
restart time -1 hour"
                        $script:ServiceChecks[$checkparams[1]] =
(get-date).AddHours(-1)
                    }
                }
                elseif ('StartPending', 'Running' -contains $winsrv.Status)
                {
                    writeLog "  -Service is running, updating last seen
time"
                    $script:ServiceChecks[$checkparams[1]] = get-date
                }
            }
        }
    }
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.xymon.com/pipermail/xymon/attachments/20181008/8ddca493/attachment.html>


More information about the Xymon mailing list