IIS站点与应用池监控:check_iis插件部署、编译与Icinga接入实践

发布时间:2026/10/26 18:29:35
IIS站点与应用池监控:check_iis插件部署、编译与Icinga接入实践 简介这是一份用 C# 编写的 IIS 监控插件源码包面向使用 Icinga2 等类 Nagios 监控系统的 Windows 运维人员用于在本机检查 IIS 站点与应用程序池状态。压缩包共 18 个文件、约 36KB以 8 个 C# 源码文件为核心并配有工程文件、配置示例、说明文档、许可协议及版本控制忽略规则便于阅读、编译和接入现有监控链路。已有 202 人学习适合想了解插件实现、配置方式与本地执行要求的读者参考并对照源码查漏补缺。插件需 .NET Framework 3.5 SP1 或 4.0、IIS 7.0 及以上环境只能由以管理员身份运行的代理或 NSCP 在本机执行源码还体现了站点与应用池匹配区分大小写、仅使用命名开关等约束可用于部署前环境核对与排错。整体结构紧凑也可作为编写 Windows 本地检查插件、理解监控命令输出与配置接入的实用样本。1. IIS 站点监控这件事最后落到一个 C# 插件上半夜两点一台 Windows Server 上十几个站点同时 503Icinga 那边只报了一条 ping 超时。登上机器才看到某个应用程序池半小时前就停了。这件事之后我才下决心装 check_iis——Icinga 自带的 Windows 模板能看 CPU、内存、磁盘唯独看不到 IIS 站点和应用程序池这一层而这层恰恰最容易出事。check_iis 是 C# 写的小插件编译出来一个 exe跑在 IIS 本机直接读本地 applicationHost.config把站点和应用程序池的状态按 Nagios 插件规范输出成退出码和 perfdata再由 NSClient 这类 agent 转给 Icinga。它适合手上有一两台以上 Windows Server 跑 IIS、并且已经有 Icinga 或 Nagios 在管的人。只想知道站点通不通一个 HTTP 检查就够想看到「池子停了但端口还开着」这种状态就得靠它。2. 装之前把环境列清.NET Framework 4.x、IIS 管理组件、管理员权限这个插件装不上九成原因都出在环境上而不在插件本身。它属于 .NET Framework 时代的老式控制台程序靠Microsoft.Web.Administration这个程序集读取 IIS 配置只要运行时、IIS 管理组件、执行权限中有一样不满足表现就是“程序运行起来但没有输出”或者“抛异常闪退”这两种情况都看不到告警。所以顺序必须是先验环境再编译、再接入。2.1 三样东西缺一不可运行时、IIS 管理组件、管理员权限第一样是 .NET Framework 4.x 运行时4.6.2 及以上都够用Server 2016 之后的系统基本自带。第二样是 IIS 的管理组件Microsoft.Web.Administration.dll就在%windir%\System32\inetsrv\下面精简过系统镜像、只装了 Web-Server 核心角色的机器上这个目录可能是空的。第三样是权限读 applicationHost.config 需要管理员级别普通用户跑必然失败。上机先跑这三条命令一分钟内出结果# 1) 查 .NET Framework 实际版本Release 值比 Version 更准 Get-ItemProperty HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full | Select-Object Version, Release # 2) 确认 IIS 管理程序集在不在 Test-Path $env:windir\System32\inetsrv\Microsoft.Web.Administration.dll # 3) 确认当前 PowerShell 是不是管理员 ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()). IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)第一条里的Release是微软用来区分 4.6.2 / 4.7.2 / 4.8 的注册表值Version字段在打了补丁的机器上常年显示 4.0.30319看着像没装新版本其实装了。第二条返回False就说明管理组件没装补装命令# 补装 IIS 管理控制台与脚本工具装完需要重新打开 PowerShell Install-WindowsFeature Web-Mgmt-Console, Web-Scripting-Tools -IncludeManagementToolsWeb-Mgmt-Console是管理控制台Web-Scripting-Tools带appcmd.exe后者在排查阶段比图形界面好用。这两项装完不需要重启但已经打开的 PowerShell 会话读不到新的 PATH重开一个更省事。2.2 版本对照Server 2016 / 2019 / 2022 与 .NET Framework 4.x我在不同批次的机器上装过系统版本和自带运行时基本是绑定的。下面这张表是我实际对过的组合装之前扫一眼能省掉很多“为什么我这里报错他那里不报”的困惑。操作系统自带 .NET Framework编译可行性备注Windows Server 20164.6.2可用建议升到 4.8老的csc.exe只支持到 C# 5Windows Server 20194.7.2可用大多数情况下开箱即用Windows Server 20224.8可用默认不带 IIS需先加角色Windows 10 / 11 开发机4.8可用适合先在本机编好再拷过去有两点容易踩一是这台机器装没装 .NET Core / .NET 6 跟这个插件完全无关不要因为看到dotnet --info有输出就以为环境齐了二是 32 位系统现在很少但老虚拟机里有上Framework64目录不存在编译脚本里的csc.exe路径要改成Framework。2.3 装完先手工跑一次基线用 WebAdministration 对一遍账在编译之前我习惯先用 PowerShell 把当前站点和应用程序池的真实状态导出一次。这份数据是后面验证插件输出对不对的唯一参照物跳过这步等插件报了个 CRITICAL你没法判断是真故障还是插件读错了。# 导入 IIS 管理模块枚举站点与应用池的当前状态 Import-Module WebAdministration Get-Website | Select-Object Name, State, PhysicalPath | Format-Table -AutoSize Get-IISAppPool | Select-Object Name, State, ManagedRuntimeVersion | Format-Table -AutoSizeGet-Website的State只有Started/Stopped两种Get-IISAppPool的State还会出现Started、Stopped、Starting。把这些输出存成文本留档后面插件输出的每个站点名都应该能在这份清单里找到对应项对不上的要么是插件读到了别的配置源要么是权限不足只读到了一部分。注意这一步必须在计划部署插件的那台机器上跑不要在跳板机或运维机上跑。WebAdministration模块读的是本机配置远程执行拿到的是远程会话的语境结果不可比。3. 编译 check_iiscsc.exe 一条命令还是 MSBuild拿到源码之后第一件事不是急着编译而是先看清楚它引用了哪些程序集。C# 项目编译失败的信息有时很误导明明缺引用报出来的却是“找不到类型或命名空间”新手容易往语法上找原因。3.1 先看清源码引用了哪几个程序集源码目录里通常是一堆.cs文件也可能带一个.csproj。有 csproj 就走 MSBuild没有 csproj 的纯源码包用csc.exe手编。先扫一遍 using# 列出所有源码文件里出现过的 using去重排序 Select-String -Path .\*.cs -Pattern ^using | Select-Object -ExpandProperty Line | Sort-Object -Unique正常的 check_iis 源码会看到System、System.Collections.Generic、System.Linq这类基础命名空间以及关键的Microsoft.Web.Administration。看到后者编译命令行里就必须显式引用%windir%\System32\inetsrv\Microsoft.Web.Administration.dll让编译器自己去 GAC 里找是不靠谱的不同机器 GAC 状态不一样。3.2 csc.exe 单命令编译不装 Visual Studio 也能出 exe很多生产服务器上不允许装几百兆的 IDE也不想为了一个几十 KB 的插件去装 Build Tools。这时候直接用系统自带的编译器最省事# 定位到 .NET Framework 4.x 自带的 C# 编译器 $csc $env:windir\Microsoft.NET\Framework64\v4.0.30319\csc.exe # 编译输出 exe平台 anycpu开启优化显式引用 IIS 管理程序集 $csc /target:exe /platform:anycpu /optimize /out:check_iis.exe /reference:System.dll /reference:System.Core.dll /reference:$env:windir\System32\inetsrv\Microsoft.Web.Administration.dll .\*.cs参数逐个说/target:exe生成控制台程序这是 Nagios 插件必须的形态/platform:anycpu让 exe 在 64 位系统上以 64 位运行读 IIS 配置更稳妥如果目标机器混着 32 位也可以写x86但要在 32 位 NSClient 下执行/optimize对这么小的程序影响不大加上是为了让 Release 产物和 Debug 产物区分开/out后面跟输出文件名/reference三个是硬依赖其中 IIS 那个必须写绝对路径。编译成功时csc.exe什么都不打印直接生成 exe。如果它吐出一堆CS0246 未能找到类型或命名空间名称八成是漏了Microsoft.Web.Administration那条引用不是代码有问题。提示这条路线有个硬限制Framework64\v4.0.30319\csc.exe只支持到 C# 5 语法。源码里只要出现字符串插值$...、nameof()、表达式体成员编译就会失败这时候不要强行改源码直接换 MSBuild。3.3 MSBuild 路线源码用了 C# 6 以上语法时只能走这条带 csproj 的源码包或者编译报CS1056: 意外的字符“$”的走 MSBuild。Build Tools 装在哪台机器上不重要可以在开发机编好再拷过去只要目标机器的 .NET Framework 版本不低于编译时的目标框架。# 用 vswhere 找 MSBuild 的真实路径别硬编码版本号目录 $vswhere ${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe $msbuild $vswhere -latest -products * -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe | Select-Object -First 1 # Release 编译AnyCPU 平台输出精简日志 $msbuild .\check_iis.csproj /p:ConfigurationRelease /p:PlatformAnyCPU /v:mvswhere是随 Visual Studio 安装器一起部署的用它拿路径比记2022\BuildTools\MSBuild\Current\Bin这种长路径可靠得多机器上装的是 2019 还是 2022 都能找到。/v:m是 minimal 日志级别报错信息一样不少屏幕干净很多。MSBuild 和 csc 编出来的 exe 功能一致区别在于 MSBuild 会照着 csproj 里的TargetFrameworkVersion自动解析引用不用你手写一堆/reference。代价是编译机上得有一套完整的构建环境第一次跑还要还原 NuGet 包如果项目引了。3.4 输出目录怎么摆路径、位数、依赖三件事exe 编出来不要随手丢在桌面或者inetsrv目录里。我统一的放法是给插件单独一个目录C:\icinga2\plugins\check_iis\ check_iis.exe Microsoft.Web.Administration.dll三条理由路径短、不带空格、不带中文NSClient 的外部脚本命令按空格切参数路径里带空格就要额外加引号很容易配错不放在System32\inetsrv是为了避免系统更新时被清理把Microsoft.Web.Administration.dll一起拷过来是为了防止目标机器上因 IIS 组件残缺而加载失败——虽然正常情况下它应该从 GAC 解析但拷一份同目录是最便宜的容错。位数也要对一遍。64 位系统上编出来的 AnyCPU exe在 32 位的宿主进程里跑会以 32 位加载这时inetsrv目录的解析路径会走SysWOW64指向的是另一套配置视图。如果我打算用 64 位的 NSClient 服务来拉起这个插件编译时就老老实实写/platform:anycpu让运行时自己决定。4. 接进 IcingaNSClient 的 NRPE 通道与命令定义插件能手工跑出结果只完成了一半。真正要解决的是“谁能定时拉起它、结果怎么回到 Icinga 里”。这一段是整个部署里配置项最多、也最容易配一半的地方。4.1 为什么插件必须落在 IIS 本机Microsoft.Web.Administration读的是本机applicationHost.config没有对外的远程读取接口。IIS 确实有个远程管理服务但那是另一套东西要开 WinRM、配委派、开防火墙为一个状态检查搞这一套不划算。结论就是插件必须放在被监控的那台 IIS 机器上由本机的 agent 进程定时执行再把结果通过 NRPE 之类的小协议送回 Icinga master。这条链路上任何一环没通Icinga 里看到的都是UNKNOWN或者干脆没数据而不是CRITICAL——这点很重要很多“装了但没报警”的案例实际是链路断了而没人发现。4.2 NSClient 侧把 exe 注册成 NRPE 外部脚本NSClient 的配置是 ini 格式主文件通常在安装目录下。要改两处外部脚本段和 NRPE 服务端段。; 允许外部脚本接收参数并放行特殊字符站点名里可能有括号、空格 [/settings/external scripts] allow arguments true allow nasty characters true ; 注册两个别名分别对应站点检查和应用池检查 [/settings/external scripts/scripts] check_iis_sites C:\icinga2\plugins\check_iis\check_iis.exe --sites check_iis_apppools C:\icinga2\plugins\check_iis\check_iis.exe --apppools ; NRPE 服务端放开参数透传端口保持默认 5666 [/settings/NRPE/server] allow arguments true allow nasty characters true port 5666allow arguments是必须的默认关闭时 NSClient 会把传进来的参数整段丢掉插件拿到的是空参数输出的永远是“全部正常”。allow nasty characters放行的是引号、括号、百分号这类字符站点名带中文括号的环境里不开这条会直接返回UNKNOWN。上面--sites/--apppools这种参数形态各版本实现不一致务必先用check_iis.exe --help看一眼真实参数名再回来改 ini 里那两行。不同的分支可能写成-t site、/site改别名后面的部分即可前半段路径不用动。改完重启服务才生效# 改完 ini 重启 NSClient服务名一般是 nscp Restart-Service nscp Get-Service nscp | Select-Object Name, Status, StartTypeStartType要确认是Automatic。有次在一台机器上看到服务是Manual重启后没人拉起Icinga 侧安静了一整天直到手工Start-Service才发现。4.3 Icinga2 侧CheckCommand 与 apply ServiceIcinga2 里定义一个基于 NRPE 的 CheckCommand把命令名透传给 NSClient 侧注册的别名// 定义一个走 NRPE 的检查命令命令名由 vars 传入 object CheckCommand check_iis { import nrpe vars.nrpe_address $address$ vars.nrpe_port 5666 vars.nrpe_command check_iis_sites vars.nrpe_timeout 30 }import nrpe引的是 Icinga2 自带的命令模板nrpe_address是主机的 address 属性nrpe_port对应 NSClient 里配的端口nrpe_command就是要调用的别名。nrpe_timeout我设 30 秒因为 IIS 上站点多的时候枚举配置会慢默认值容易误判超时。再用apply Service批量挂到所有 IIS 角色主机上// 站点检查所有标了 iis 角色的 Windows 主机自动挂上 apply Service iis-sites { import generic-service check_command check_iis vars.nrpe_command check_iis_sites check_interval 2m retry_interval 30s max_check_attempts 3 assign where host.vars.os windows host.vars.role iis } // 应用池检查复用同一个 CheckCommand只换别名 apply Service iis-apppools { import generic-service check_command check_iis vars.nrpe_command check_iis_apppools check_interval 2m max_check_attempts 3 assign where host.vars.os windows host.vars.role iis }max_check_attempts 3配retry_interval 30s是我在应用池场景下的固定搭配。IIS 回收应用池的瞬间状态会短暂变成Starting只查一次就报警会产生大量没有意义的告警给三次重试、间隔半分钟基本能过滤掉回收窗口内的抖动。改完必须做一次配置语法校验不要直接 reload# 校验配置语法不通过会明确指出行号 icinga2 daemon -C # 校验通过后再 reload避免把坏配置推上去 systemctl reload icinga24.4 阈值与 perfdata告警线怎么定才不吵插件按 Nagios 规范返回退出码Icinga 直接映射成状态。搞清这张表后面调阈值就不会瞎改退出码Nagios/Icinga 状态典型触发场景0OK所有站点和池子都 Started1WARNING数量与基线不符、单个池子处于 Starting2CRITICAL有站点或池子 Stopped3UNKNOWN参数错误、权限不足、程序集加载失败阈值我一般这样定站点或应用池状态不是Started直接 CRITICAL总数与上次基线差超过 2 个报 WARNING用来发现有人手工删站点Default Web Site和几个明确已下线的老站点加白名单不进检查范围。白名单这一步很关键很多环境里躺着五六个历史遗留站点一装上就是一片红值班的人两天就对这个检查脱敏了。perfdata 不要忽略。插件输出里带站点数25;;;0;30这种格式的数值Icinga Web 里能直接画趋势图。有次某个池子的重启次数曲线一周内翻了四倍人还没收到告警看图就先发现了内存泄漏的苗头。5. 避坑与排查五条踩过的记录5.1 编译通过运行就报 FileNotFoundException现象csc.exe编译零报错双击 exe 一闪而过在 PowerShell 里跑报Could not load file or assembly Microsoft.Web.Administration。原因编译期用绝对路径找到了inetsrv下的 dll运行期程序集解析走的是另一套探测顺序GAC 里没注册或者注册的是别的版本就加载失败。解决把Microsoft.Web.Administration.dll从%windir%\System32\inetsrv\拷一份到 exe 同目录。同目录的优先级最高加载一定成功。拷的时候注意位数64 位系统上要拷System32下的那一份。5.2 csc 编译报 CS1056 意外的字符“$”现象源码明明在别人的机器上编得过到了这台服务器上满屏CS1056、CS1525指向的行里都有$...或。原因Framework64\v4.0.30319\csc.exe是 .NET Framework 时代的旧编译器语言版本锁在 C# 5字符串插值和表达式体成员都是 C# 6 才有的。解决换 MSBuild 路线或者用 Roslyn 编译器包。不要试图把源码里的$...手工改回string.Format改一处漏一处还会破坏后续升级。5.3 NSClient 返回 UNKNOWN: No handler for command现象Icinga 里这个 Service 一直是 UNKNOWN手工从 master 上check_nrpe -H ip -c check_iis_sites返回No handler for command。原因ini 里的别名没生效或者改完没重启服务。还有一种情况是 ini 写在了[/settings/external scripts/scripts]之外段落名拼错一个字母就整段失效。解决先Restart-Service nscp再从 master 上直接跑check_nrpe定位。如果还是不行用nscp test进交互模式show settings看别名到底加载进去没有。定位到这一步问题基本就明了了。5.4 中文站点名让 Icinga 显示乱码现象插件在命令行里跑中文站点名正常经过 NRPE 到 Icinga 里变成一串问号或者服务状态直接跳到 UNKNOWN。原因Windows 控制台默认代码页是 GBK插件输出的字节流没转成 UTF-8Icinga 侧按 UTF-8 解析就乱了perfdata 里有非 ASCII 字符时解析器还可能直接放弃。解决在 NSClient 的 ini 里给这个脚本加环境变量或者干脆在 Icinga 侧给 Service 加vars.nrpe_command时避开含中文的站点。最稳的做法是把站点命名规范统一成英文中文名只留在显示名里——这件事推起来费劲但推成之后省下的排查时间远超成本。5.5 服务账户换成域账号后全部 AccessDenied现象原本 LocalSystem 跑得好好的安全部门要求服务改用自己的域账号改完之后所有检查返回CRITICAL或UNKNOWN事件日志里是Filename: redirection.config, Error: 无法读取配置文件。原因读applicationHost.config需要管理员权限域账号默认不在本机管理员组IIS 的配置委派也没给它授权。解决两条路选一条。一是把这个域账号加进本机 Administrators简单但扩大了权限面二是保持服务以 LocalSystem 运行用 NSClient 自己的访问控制限制来源 IP权限不扩散。我一般选第二条把allowed hosts收紧到 Icinga master 的地址比给一个域账号开管理员干净。6. 装完怎么验证把一次 CRITICAL 真的打出来检查项装完显示一片绿色说明不了任何问题。绿灯可能意味着“真的都好”也可能意味着“插件根本没跑起来Icinga 默认给了个 OK”。我踩过一次后者服务账户权限不足插件每次都异常退出但退出码被包装成了 0绿了整整三周。所以验证的核心思路是反向验证——主动制造一次故障看告警能不能按时打出来。6.1 三段式验证本机 → NRPE → Icinga 强制告警第一段在本机直接跑拿到原始输出# 直接执行插件看退出码和输出文本 C:\icinga2\plugins\check_iis\check_iis.exe --apppools # 立即查看上一条命令的退出码0/1/2/3 $LASTEXITCODE这一段要确认三件事输出里能列出所有应用池名字、$LASTEXITCODE是 0、文本末尾有 perfdata。少任何一项都不用往下走先解决这一段。第二段从 Icinga master 上通过 NRPE 调# 从 master 侧走 NRPE 通道验证链路是否通 /usr/lib/nagios/plugins/check_nrpe -H 10.0.0.21 -c check_iis_apppools -t 30 # 参数透传也要验一次确认 allow arguments 真的生效 /usr/lib/nagios/plugins/check_nrpe -H 10.0.0.21 -c check_iis_sites -a --warning 2第二条是关键。如果allow arguments没开加上-a之后输出不变你就能确定参数被吞了。这一步过了说明 NSClient 侧配置没问题剩下的都是 Icinga 配置。第三段制造故障。挑一个测试用的应用池手工停掉等一个检查周期# 停掉测试应用池制造一次真实的 CRITICAL Stop-WebAppPool -Name TestPool Start-Sleep -Seconds 150 # 验证完记得拉起来别留在生产上 Start-WebAppPool -Name TestPool预期结果是Icinga Web 里iis-apppools这个 Service 在 2 到 3 分钟内变红状态输出里明确指出TestPool是Stopped并且这个状态在恢复后自动转回绿色。三个现象缺一个就回头查对应的那一段——没变红查链路变红了但没恢复查max_check_attempts和重试间隔。6.2 验证清单装完每台机器我都照着这张表过一遍五分钟的事能挡掉后面几周的反复。验证项执行位置期望结果插件单独执行IIS 本机退出码 0输出含全部站点名参数解析IIS 本机--help有输出参数不报错NRPE 无参调用Icinga master返回 OK 与完整文本NRPE 带参调用Icinga master参数生效输出随之变化配置语法Icinga mastericinga2 daemon -C零报错故障注入IIS 本机3 分钟内变 CRITICAL恢复后回 OKperfdataIcinga Web图形里出现站点/池子数量曲线服务自启IIS 本机NSClient 为 Automatic 且 Running故障注入这一步不要省。我见过太多“配完了看着挺好”的环境真出事那天才发现告警从来没通过。宁可在一个工作日的下午手工停一个池子看它红一次也别等半夜三点靠运气。从那以后我每装一台 IIS 节点都强制走一遍「本机直跑 → master 走 NRPE → 手工停池子看它变红」这三步一步不落。绿灯不值钱能变红又能自己变回绿的绿灯才值钱。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询