news 2026/9/14 11:41:28

Telegraf win_services 插件详解:在 Windows 上监控系统服务运行状态与启动模式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Telegraf win_services 插件详解:在 Windows 上监控系统服务运行状态与启动模式

Telegraf win_services 插件详解:在 Windows 上监控系统服务运行状态与启动模式

【免费下载链接】telegrafAgent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.项目地址: https://gitcode.com/GitHub_Trending/te/telegraf

Telegraf 的win_services输入插件用于采集 Windows 系统上服务的运行状态(state)与启动类型(startup_mode),支持通过通配符按服务名筛选采集范围。本篇围绕官方插件文档展开,结合插件源码解析其服务枚举、过滤匹配与错误处理的完整实现机制,帮助你在 Windows 主机上落地一套完整的服务状态监控方案。

插件定位与平台限制

根据插件文档,win_services用于收集 Windows 服务的状态信息,并且仅支持 Windows 平台。文档同时特别提示:

监控某些服务可能需要以管理员权限运行 Telegraf。

从源码结构可以印证这一点。真实实现文件 win_services.go 顶部带有//go:build windows构建标签,而 win_services_notwindows.go 为非 Windows 平台提供了一个空实现(stub),其Init()仅输出一条 "Current platform is not supported" 警告,Gather不做任何采集。这意味着在 Linux/macOS 上配置该插件不会报错,但也不会产生任何指标。

配置说明

插件的完整配置示例如下(来自 sample.conf,该文件通过//go:embed内嵌进二进制,可直接由telegraf --usage查看):

# Input plugin to report Windows services info. # This plugin ONLY supports Windows [[inputs.win_services]] ## Names of the services to monitor. Leave empty to monitor all the available ## services on the host. Globs accepted. Case insensitive. service_names = [ "LanmanServer", "TermService", "Win*", ] # optional, list of service names to exclude excluded_service_names = ['WinRM']

配置参数与源码中的结构体一一对应:

配置项源码字段说明
service_namesServiceNames []string要监控的服务名列表,支持通配符(glob)且不区分大小写;留空则监控主机上所有服务
excluded_service_namesServiceNamesExcluded []string可选的排除列表,同样支持通配符,用于从采集结果中剔除指定服务

此外,插件还支持 Telegraf 的全局插件配置选项(如aliastagsignore_empty等),详见 CONFIGURATION.md。

大小写不敏感的匹配实现

service_names的"不区分大小写"并非简单注释,而是有明确的源码依据。在 win_services.go 的Init()中,插件将 include 与 exclude 列表中的每个名称统一转换为小写:

func (m *WinServices) Init() error { // For case insensitive comparison (see issue #8796) we need to transform the services // to lowercase servicesInclude := make([]string, 0, len(m.ServiceNames)) for _, s := range m.ServiceNames { servicesInclude = append(servicesInclude, strings.ToLower(s)) } servicesExclude := make([]string, 0, len(m.ServiceNamesExcluded)) for _, s := range m.ServiceNamesExcluded { servicesExclude = append(servicesExclude, strings.ToLower(s)) } f, err := filter.NewIncludeExcludeFilter(servicesInclude, servicesExclude) if err != nil { return err } m.servicesFilter = f return nil }

对应的匹配逻辑在listServices中:枚举出的每个服务名同样转小写后再交给过滤器判断——

func (m *WinServices) listServices(scmgr winServiceManager) ([]string, error) { names, err := scmgr.listServices() if err != nil { return nil, fmt.Errorf("could not list services: %w", err) } var services []string for _, name := range names { // Compare case-insensitive. Use lowercase as we already converted the filter to use it. n := strings.ToLower(name) if m.servicesFilter.Match(n) { services = append(services, name) } } return services, nil }

底层过滤器是 Telegraf 的通用filter包。filter.NewIncludeExcludeFilter默认以includeDefault=true, excludeDefault=false构造IncludeExcludeFilter(见 filter.go),其Match语义为:include 列表为空时默认放行一切;非空则必须命中,且命中 exclude 的服务始终被剔除。这解释了为什么留空service_names会采集全部服务,而同时配置两者时excluded_service_names具有更高优先级。通配符(如Win*)的匹配由 implementations.go 中的filterGlobMultiple基于 glob 编译模式实现;若全部模式均不含 glob 字符,则退化为基于哈希集合的精确匹配,性能更优。

采集流程与底层实现

每次采集(Gather)的核心调用链如下,全部封装在 win_services.go 中:

  1. 连接服务控制管理器mgProvider.connect()调用windows.OpenSCManager(nil, nil, windows.GENERIC_READ)以只读权限打开 SCManager,并包装为mgr.Mgr。只读权限意味着该插件只能查询、不会修改任何服务。
  2. 枚举服务listServices()通过mgr.Mgr.ListServices()拿到系统服务名列表,再经servicesFilter过滤。
  3. 逐服务查询:对每个候选服务执行openServicewindows.OpenServiceGENERIC_READ句柄)→Query()获取运行时状态 →Config()获取服务配置,最后通过acc.AddFields("win_services", fields, tags)输出指标。

这里有一个值得注意的实现细节:display_name标签是条件性添加的——

tags := map[string]string{ "service_name": service.ServiceName, } // display name could be empty, but still valid service if len(service.DisplayName) > 0 { tags["display_name"] = service.DisplayName }

即服务没有显示名时该标签不会出现,而不是写入空值。在下游做 tag 基数分析或告警规则匹配时需要注意这一点。

错误处理与权限行为

Gather对错误采取了"整体失败与单项跳过"分离的策略:

  • SCManager 连接失败或服务列表获取失败:直接返回错误,整轮采集失败。这一点被单元测试 win_services_test.go 中的TestMgrErrors覆盖(通过FakeMgProvider注入mgrConnectErrormgrListServicesError验证错误向上传播)。
  • 单个服务的打开/查询/配置失败:仅记录日志并continue,不影响其他服务的采集。其中权限错误(fs.ErrPermission,即ERROR_ACCESS_DENIED一类错误)通过isPermission判定后降级为Debug 级别日志,其他错误才记Error 级别——因为非管理员运行时对部分服务无访问权是常见且可预期的情况,不应产生大量告警日志。

TestServiceErrors测试用例通过fakeWinSvc分别注入serviceOpenErrorserviceQueryErrorserviceConfigError三种故障,验证了上述"记日志但不中断"的行为。

测试与验证方式

  • 单元测试(win_services_test.go):基于接口抽象winServiceManager/managerProvider,用假实现模拟服务管理器,验证了 glob 包含匹配(TestGatherContainsTag)、glob 排除匹配(TestExcludingNamesTag)以及各种错误路径。
  • 集成测试(win_services_integration_test.go):文件头明确注明 "these tests must be run under administrator account",即需要管理员权限的 Windows 环境运行。TestListIntegration验证LanmanServerTermService两个已知服务能被精确过滤出,TestEmptyListIntegration验证空配置能枚举出 20 个以上服务,TestGatherErrorsIntegration则用不存在的非法服务名验证错误计数。

如果你需要按自定义构建裁剪 Telegraf(只编译所需插件),该插件的注册入口为 win_services.go,构建标签为inputs.win_services

指标说明

插件输出单一指标名win_services,其结构与取值范围如下:

Tags:

标签说明
service_name服务名(SCManager 内部名称),始终存在
display_name服务显示名,可能为空(为空时该标签不输出)

Fields:

字段类型说明
stateinteger服务运行状态
startup_modeinteger服务启动类型

state的取值(对应svc.Status.State):

  • 1- stopped(已停止)
  • 2- start pending(正在启动)
  • 3- stop pending(正在停止)
  • 4- running(运行中)
  • 5- continue pending(正在继续)
  • 6- pause pending(正在暂停)
  • 7- paused(已暂停)

startup_mode的取值(对应mgr.Config.StartType):

  • 0- boot start(启动时启动)
  • 1- system start(系统启动时启动)
  • 2- auto start(自动启动)
  • 3- demand start(手动/按需启动)
  • 4- disabled(禁用)

示例输出(来自插件文档):

win_services,host=WIN2008R2H401,display_name=Server,service_name=LanmanServer state=4i,startup_mode=2i 1500040669000000000 win_services,display_name=Remote\ Desktop\ Services,service_name=TermService,host=WIN2008R2H401 state=1i,startup_mode=3i 1500040669000000000

可以直观看出:LanmanServer(Server 服务)处于运行中(state=4i)、自动启动(startup_mode=2i);而TermService(远程桌面服务)处于停止(state=1i)、手动启动(startup_mode=3i)。由于display_name中可能含空格与反斜杠转义(如Remote\ Desktop\ Services),后续解析需按 InfluxDB Line Protocol 规则处理。

实战配置建议

结合文档与源码行为,一个典型的监控"关键服务是否停止"的配置可以这样写:

[[inputs.win_services]] ## 只关注关键服务,通配符覆盖所有 Windows Update 相关服务 service_names = [ "LanmanServer", "TermService", "Wuauserv", "W32Time", ] ## 排除不需要纳入采集范围的服务 excluded_service_names = ["WinRM"]

使用时的几个要点:

  1. 权限:以普通用户运行时,无权限的服务会以 Debug 日志静默跳过,指标会缺失但进程不报错。为保证指标完整,建议以管理员权限运行(Windows 服务方式部署 Telegraf 时通常满足此条件)。
  2. 状态判断state是瞬态枚举值,2/3/5/6属于过渡态,做"服务已停止"告警时应重点判断state == 1且持续若干个采集周期,避免把正在重启的服务误报。
  3. 启动模式告警startup_mode可用于发现配置漂移,例如核心服务startup_mode2(auto)变为3(demand)或4(disabled)时可触发通知。
  4. 平台前提:该插件只在实际编译目标为 Windows 时生效;在 Linux 上运行同一配置只会收到一条 "Current platform is not supported" 警告,不会报错也不会采集。

小结

win_services插件以只读权限连接 Windows SCManager,枚举服务后按 glob 过滤,输出statestartup_mode两个整型字段。其源码通过接口抽象(winServiceManager/managerProvider)实现了对服务管理器的解耦,使单元测试无需真实系统依赖;对权限错误的降级处理则保证了非管理员场景下的日志安静。相关实现与测试可分别在 win_services.go、win_services_test.go 与 win_services_integration_test.go 中查阅。

【免费下载链接】telegrafAgent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.项目地址: https://gitcode.com/GitHub_Trending/te/telegraf

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 11:40:55

[git] 忽略已经提交的文件或文件夹

目录 1. 问题背景2. 原因分析3. 解决方案 3.1 移除单个文件3.2 移除整个文件夹3.3 完整操作示例3.4 git rm 与 git rm --cached 对比3.5 实战:忽略已跟踪的日志文件 4. 注意事项5. 常见问题排查 5.1 git rm --cached 后文件仍被跟踪怎么办?5.2 误删本地…

作者头像 李华
网站建设 2026/9/14 11:39:16

C#实现测绘后方交会坐标解算与精度验证

简介:本资源是一个基于C#开发的测绘专业后方交会计算程序,面向测绘工程学生、测量技术人员及C#初学者,解决未知点坐标解算这一典型测量问题。程序完整实现了数据输入、方位角转换、线性方程组求解、误差分析与结果输出等核心流程,…

作者头像 李华
网站建设 2026/9/14 11:38:39

量子编程中的观察者效应解析与调试技巧

## 1. 量子纠缠测试中的"观察者效应"现象解析去年在开发量子计算模拟器时,我遇到一个诡异现象:单元测试中明明存在的bug,一旦开启调试模式就会消失。这种"量子特性"般的bug让我花了三周时间才找到根源。后来发现这与量子…

作者头像 李华