Skip to content

Commit 26e96d7

Browse files
committed
check_service: make service filter case insensitive
1 parent 037b5de commit 26e96d7

7 files changed

+77
-21
lines changed

Changes

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ next:
66
- change like operator to be case insensitive
77
- add new slike operator which is case sensitive
88
- add support for str() operator
9-
- check_process: make process filter is case insensitive
9+
- check_process: make process filter case insensitive
10+
- check_service: make service filter case insensitive
1011

1112
0.31 Wed Feb 12 18:14:54 CET 2025
1213
- fix check_files thresholds on total_size

docs/checks/commands/check_service_linux.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,10 @@ Naemon Config
6767

6868
## Check Specific Arguments
6969

70-
| Argument | Description |
71-
| -------- | ---------------------------------------------------------------------------------- |
72-
| exclude | List of services to exclude from the check (mainly used when service is set to \*) |
73-
| service | Name of the service to check (set to \* to check all services). Default: \* |
70+
| Argument | Description |
71+
| -------- | ----------------------------------------------------------------------------------------------------- |
72+
| exclude | List of services to exclude from the check (mainly used when service is set to \*) (case insensitive) |
73+
| service | Name of the service to check (set to \* to check all services). (case insensitive) Default: \* |
7474

7575
## Attributes
7676

docs/checks/commands/check_service_windows.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ Naemon Config
6363

6464
## Check Specific Arguments
6565

66-
| Argument | Description |
67-
| -------- | ---------------------------------------------------------------------------------- |
68-
| exclude | List of services to exclude from the check (mainly used when service is set to \*) |
69-
| service | Name of the service to check (set to \* to check all services). Default: \* |
66+
| Argument | Description |
67+
| -------- | ----------------------------------------------------------------------------------------------------- |
68+
| exclude | List of services to exclude from the check (mainly used when service is set to \*) (case insensitive) |
69+
| service | Name of the service to check (set to \* to check all services). (case insensitive) Default: \* |
7070

7171
## Attributes
7272

pkg/snclient/check_service_common.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ func (l *CheckService) addServiceMetrics(service string, serviceState float64, c
147147
}
148148

149149
func (l *CheckService) isRequired(check *CheckData, entry map[string]string, services, excludes []string) bool {
150-
name := entry["name"]
151-
desc := entry["desc"]
150+
name := strings.ToLower(entry["name"])
151+
desc := strings.ToLower(entry["desc"])
152152
if slices.Contains(excludes, name) || slices.Contains(excludes, desc) {
153153
log.Tracef("service %s excluded by exclude list", name)
154154

@@ -157,7 +157,11 @@ func (l *CheckService) isRequired(check *CheckData, entry map[string]string, ser
157157
if slices.Contains(services, "*") {
158158
return true
159159
}
160-
if len(services) > 0 && !slices.Contains(services, name) && !slices.Contains(services, desc) {
160+
161+
foundByName := slices.ContainsFunc(services, func(e string) bool { return strings.EqualFold(e, name) })
162+
foundByDesc := slices.ContainsFunc(services, func(e string) bool { return strings.EqualFold(e, desc) })
163+
164+
if len(services) > 0 && !foundByName && !foundByDesc {
161165
log.Tracef("service %s excluded by not matching service list", name)
162166

163167
return false

pkg/snclient/check_service_linux.go

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ var (
2222
reSvcStatic = regexp.MustCompile(`;\sstatic\)`)
2323
reSvcActive = regexp.MustCompile(`\s*Active:\s+(\S+)`)
2424
reSvcFirstLine = regexp.MustCompile(`^.\s(\S+)\.service\s+`)
25+
reSvcNameLine = regexp.MustCompile(`^\s*(\S+)\.service\s+`)
2526
)
2627

2728
const (
2829
systemctlStatusCmd = "systemctl status --lines=0 --no-pager --quiet"
30+
systemctlNames = "systemctl list-units --lines=0 --no-pager --quiet --no-legend"
2931
)
3032

3133
type CheckService struct {
@@ -61,10 +63,10 @@ There is a specific [check_service for windows](../check_service_windows) as wel
6163
"service": {
6264
value: &l.services,
6365
isFilter: true,
64-
description: "Name of the service to check (set to * to check all services). Default: *",
66+
description: "Name of the service to check (set to * to check all services). (case insensitive) Default: *",
6567
defaultCritical: stateCondition,
6668
},
67-
"exclude": {value: &l.excludes, description: "List of services to exclude from the check (mainly used when service is set to *)"},
69+
"exclude": {value: &l.excludes, description: "List of services to exclude from the check (mainly used when service is set to *) (case insensitive)"},
6870
},
6971
defaultFilter: "active != inactive",
7072
defaultCritical: stateCondition + " && preset != 'disabled'",
@@ -111,6 +113,11 @@ Check memory usage of specific service:
111113
func (l *CheckService) Check(ctx context.Context, snc *Agent, check *CheckData, _ []Argument) (*CheckResult, error) {
112114
l.snc = snc
113115

116+
// make excludes case insensitive
117+
for i := range l.excludes {
118+
l.excludes[i] = strings.ToLower(l.excludes[i])
119+
}
120+
114121
if len(l.services) == 0 || slices.Contains(l.services, "*") {
115122
// fetch status of all services at once instead of calling systemctl over and over
116123
output, stderr, _, err := snc.execCommand(ctx, fmt.Sprintf("%s --type=service --all", systemctlStatusCmd), DefaultCmdTimeout)
@@ -131,7 +138,7 @@ func (l *CheckService) Check(ctx context.Context, snc *Agent, check *CheckData,
131138
}
132139
found := false
133140
for _, e := range check.listData {
134-
if e["name"] == service {
141+
if strings.EqualFold(e["name"], service) {
135142
found = true
136143

137144
break
@@ -156,6 +163,20 @@ func (l *CheckService) Check(ctx context.Context, snc *Agent, check *CheckData,
156163
}
157164

158165
func (l *CheckService) addServiceByName(ctx context.Context, check *CheckData, service string, services, excludes []string) error {
166+
err := l.addServiceByExactName(ctx, check, service, services, excludes)
167+
if err == nil {
168+
return nil
169+
}
170+
171+
realService := l.findServiceByName(ctx, service)
172+
if realService == "" {
173+
return err
174+
}
175+
176+
return l.addServiceByExactName(ctx, check, realService, services, excludes)
177+
}
178+
179+
func (l *CheckService) addServiceByExactName(ctx context.Context, check *CheckData, service string, services, excludes []string) error {
159180
output, stderr, _, err := l.snc.execCommand(ctx, fmt.Sprintf("%s %s.service ", systemctlStatusCmd, service), DefaultCmdTimeout)
160181
if err != nil {
161182
return fmt.Errorf("systemctl failed: %s\n%s", err.Error(), stderr)
@@ -307,7 +328,7 @@ func (l *CheckService) parseAllServices(ctx context.Context, check *CheckData, o
307328
}
308329
service := serviceMatches[1]
309330

310-
if slices.Contains(l.excludes, service) {
331+
if slices.Contains(l.excludes, strings.ToLower(service)) {
311332
log.Tracef("service %s excluded by 'exclude' argument", service)
312333

313334
continue
@@ -322,3 +343,25 @@ func (l *CheckService) parseAllServices(ctx context.Context, check *CheckData, o
322343

323344
return nil
324345
}
346+
347+
func (l *CheckService) findServiceByName(ctx context.Context, service string) (name string) {
348+
output, _, _, err := l.snc.execCommand(ctx, systemctlNames, DefaultCmdTimeout)
349+
if err != nil {
350+
log.Tracef("systemctl failed: %s", err.Error())
351+
352+
return ""
353+
}
354+
355+
services := strings.Split(output, "\n")
356+
for _, svc := range services {
357+
match := reSvcNameLine.FindStringSubmatch(svc)
358+
if len(match) > 1 {
359+
realService := strings.TrimSpace(match[1])
360+
if strings.EqualFold(realService, service) {
361+
return realService
362+
}
363+
}
364+
}
365+
366+
return ("")
367+
}

pkg/snclient/check_service_windows.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ There is a specific [check_service for linux](../check_service_linux) as well.`,
5858
"service": {
5959
value: &l.services,
6060
isFilter: true,
61-
description: "Name of the service to check (set to * to check all services). Default: *",
61+
description: "Name of the service to check (set to * to check all services). (case insensitive) Default: *",
6262
defaultWarning: "state != 'running'",
6363
defaultCritical: "state != 'running'",
6464
},
65-
"exclude": {value: &l.excludes, description: "List of services to exclude from the check (mainly used when service is set to *)"},
65+
"exclude": {value: &l.excludes, description: "List of services to exclude from the check (mainly used when service is set to *) (case insensitive)"},
6666
},
6767
defaultFilter: "none",
6868
defaultCritical: "state != 'running' && start_type = 'auto'",
@@ -137,7 +137,7 @@ func (l *CheckService) Check(ctx context.Context, _ *Agent, check *CheckData, _
137137
}
138138

139139
for _, service := range serviceList {
140-
if slices.Contains(l.excludes, strings.TrimSpace(service)) {
140+
if slices.Contains(l.excludes, strings.ToLower(strings.TrimSpace(service))) {
141141
log.Tracef("service %s excluded by 'exclude' argument", service)
142142

143143
continue
@@ -157,7 +157,7 @@ func (l *CheckService) Check(ctx context.Context, _ *Agent, check *CheckData, _
157157
}
158158
found := false
159159
for _, e := range check.listData {
160-
if e["name"] == service || e["desc"] == service {
160+
if strings.EqualFold(e["name"], service) || strings.EqualFold(e["desc"], service) {
161161
found = true
162162

163163
break
@@ -361,7 +361,10 @@ func (l *CheckService) GetNameByDisplayName(name string) (string, error) {
361361
}
362362

363363
for _, s := range l.AllServices {
364-
if s.DisplayName == name {
364+
if strings.EqualFold(s.DisplayName, name) {
365+
return s.Name, nil
366+
}
367+
if strings.EqualFold(s.Name, name) {
365368
return s.Name, nil
366369
}
367370
}

pkg/snclient/check_service_windows_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,9 @@ func TestCheckService(t *testing.T) {
2424
res = snc.RunCheck("check_service", []string{"service=Server"})
2525
assert.Equalf(t, CheckExitOK, res.State, "state OK")
2626
assert.Containsf(t, string(res.BuildPluginOutput()), "OK - All 1 service", "output matches")
27+
28+
// search service by non case name
29+
res = snc.RunCheck("check_service", []string{"service=server"})
30+
assert.Equalf(t, CheckExitOK, res.State, "state OK")
31+
assert.Containsf(t, string(res.BuildPluginOutput()), "OK - All 1 service", "output matches")
2732
}

0 commit comments

Comments
 (0)