Red Hat Training

A Red Hat training course is available for Red Hat Enterprise Linux

21.7. 使用 Net-SNMP 监控性能

红帽企业 Linux 7 包含 Net-SNMP 软件 套件,其中包括灵活且可扩展的 简单网络管理协议 (SNMP)代理。此代理及其相关实用程序可用于提供从大量系统到支持 SNMP 协议轮询的各种工具的性能数据。

本节介绍将 Net-SNMP 代理配置为通过网络安全地提供性能数据,使用 SNMP 协议检索数据,以及扩展 SNMP 代理以提供自定义性能指标。

21.7.1. 安装 Net-SNMP

Net-SNMP 软件套件可作为 Red Hat Enterprise Linux 软件分发包中的一组 RPM 软件包使用。表 21.2 “可用的 Net-SNMP 软件包” 总结了每个软件包及其内容。

表 21.2. 可用的 Net-SNMP 软件包

软件包Provides

net-snmp

SNMP 代理后台程序和文档.导出性能数据时需要此软件包。

net-snmp-libs

nets nmp 库和捆绑 的管理信息库( MIBs)。导出性能数据时需要此软件包。

net-snmp-utils

SNMP 客户端,如 snmpgetsnmpwalk.需要这个软件包才能通过 SNMP 查询系统性能数据。

net-snmp-perl

mib2c 程序和 NetSNMP Perl 模块。请注意,这个软件包由可选频道提供。有关红帽附加频道的详情,请查看 第 9.5.7 节 “添加 Optional 和 Supplementary 存储库”

net-snmp-python

适用于 Python 的 SNMP 客户端库。请注意,这个软件包由可选频道提供。有关红帽附加频道的详情,请查看 第 9.5.7 节 “添加 Optional 和 Supplementary 存储库”

要安装这些软件包,请使用以下格式的 yum 命令:

yum install package…

例如,要安装本节其余部分中使用的 SNMP 代理守护进程和 SNMP 客户端,以 root 用户身份在 shell 提示符后输入以下内容:

~]# yum install net-snmp net-snmp-libs net-snmp-utils

有关如何在 Red Hat Enterprise Linux 中安装新软件包的详情请参考 第 9.2.4 节 “安装软件包”

21.7.2. 运行 Net-SNMP 守护进程

net-snmp 软件包包含 snmpd,即 SNMP 代理守护进程。本节介绍如何启动、停止和重新启动 snmpd 服务。有关在 Red Hat Enterprise Linux 7 中管理系统服务的详情请参考 第 10 章 使用 systemd 管理服务

21.7.2.1. 启动服务

要在当前会话中运行 snmpd 服务,以 root 用户身份在 shell 提示符后输入以下内容:

systemctl start snmpd.service

要将服务配置为在引导时自动启动,请使用以下命令:

systemctl enable snmpd.service

21.7.2.2. 停止服务

要停止正在运行的 snmpd 服务,以 root 用户身份在 shell 提示符后输入以下内容:

systemctl stop snmpd.service

要禁用在引导时启动服务,请使用以下命令:

systemctl disable snmpd.service

21.7.2.3. 重启服务

要重启正在运行的 snmpd 服务,在 shell 提示符后输入以下内容:

systemctl restart snmpd.service

此命令将停止服务,并快速启动该服务。要在不停止服务的情况下重新载入配置,请运行以下命令:

systemctl reload snmpd.service

这会导致正在运行的 snmpd 服务重新加载其配置。

21.7.3. 配置 Net-SNMP

要更改 Net-SNMP 代理守护进程配置,请编辑 /etc/snmp/snmpd.conf 配置文件。Red Hat Enterprise Linux 7 中包含的默认 snmpd.conf 文件会受到大量注释,它可作为代理配置的良好起点。

本节重点介绍两种常见任务:设置系统信息和配置身份验证。有关可用配置指令的更多信息,请参阅 snmpd.conf(5)手册页。此外,net -snmp 软件包中也有一个名为 snmp conf 的实用程序,可用于以交互方式生成有效的代理配置。

请注意,必须安装 net-snmp-utils 软件包,才能使用本节中描述的 snmpwalk 实用程序。

注意

要将配置文件的任何更改生效,请以 root 用户身份 运行以下命令来强制 snmpd 服务重新读取配置:

systemctl reload snmpd.service

21.7.3.1. 设置系统信息

net-SNMP 通过系统树提供一些基本 系统 信息。例如,以下 snmpwalk 命令显示具有默认代理配置的 系统 树:

~]# snmpwalk -v2c -c public localhost system
SNMPv2-MIB::sysDescr.0 = STRING: Linux localhost.localdomain 3.10.0-123.el7.x86_64 #1 SMP Mon May 5 11:16:57 EDT 2014 x86_64
SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-MIB::netSnmpAgentOIDs.10
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (464) 0:00:04.64
SNMPv2-MIB::sysContact.0 = STRING: Root <root@localhost> (configure /etc/snmp/snmp.local.conf)
[output truncated]

默认情况下,sysName 对象被设置为主机名。通过更改 sys location 和 sys contact 指令的值,可以在 /etc/snmp/snmpd.conf 文件中配置 sys Location 和 sys Contact 对象,例如:

syslocation Datacenter, Row 4, Rack 3
syscontact UNIX Admin <admin@example.com>

更改配置文件后,重新载入配置并再次运行 snmpwalk 命令测试它:

~]# systemctl reload snmp.service
~]# snmpwalk -v2c -c public localhost system
SNMPv2-MIB::sysDescr.0 = STRING: Linux localhost.localdomain 3.10.0-123.el7.x86_64 #1 SMP Mon May 5 11:16:57 EDT 2014 x86_64
SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-MIB::netSnmpAgentOIDs.10
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (35424) 0:05:54.24
SNMPv2-MIB::sysContact.0 = STRING: UNIX Admin <admin@example.com>
SNMPv2-MIB::sysName.0 = STRING: localhost.localdomain
SNMPv2-MIB::sysLocation.0 = STRING: Datacenter, Row 4, Rack 3
[output truncated]

21.7.3.2. 配置身份验证

Net-SNMP 代理守护进程支持所有三种版本的 SNMP 协议。前两个版本(1 和 2c)提供使用社区字符串的简单身份验证。此字符串是代理和任何客户端实用程序之间的共享 secret。字符串通过网络以明文形式传递,但被视为不安全。SNMP 协议的版本 3 支持使用各种协议进行用户身份验证和消息加密。Net-SNMP 代理还支持通过 SSH 隧道以及 X.509 证书的 TLS 身份验证。

配置 SNMP 版本 2c 社区

要配置 SNMP 版本 2c 社区,请在 /etc/snmp/snmpd.conf 配置文件中使用 rocommunityrwcommunity 指令。指令的格式如下:

directive community source OID

其中社区是要使用的社区字符串 ,source 是 IP 地址或子网,OID 则是 SNMP 树,用于提供对.例如,以下指令提供了对 系统 树的只读访问,使用本地机器上的社区字符串"redhat":

rocommunity redhat 127.0.0.1 .1.3.6.1.2.1.1

要测试配置,请使用 snmpwalk 命令及 -v-c 选项。

~]# snmpwalk -v2c -c redhat localhost system
SNMPv2-MIB::sysDescr.0 = STRING: Linux localhost.localdomain 3.10.0-123.el7.x86_64 #1 SMP Mon May 5 11:16:57 EDT 2014 x86_64
SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-MIB::netSnmpAgentOIDs.10
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (101376) 0:16:53.76
SNMPv2-MIB::sysContact.0 = STRING: UNIX Admin <admin@example.com>
SNMPv2-MIB::sysName.0 = STRING: localhost.localdomain
SNMPv2-MIB::sysLocation.0 = STRING: Datacenter, Row 4, Rack 3
[output truncated]
配置 SNMP 版本 3 用户

要配置 SNMP 版本 3 用户,请使用 net-snmp-create-v3-user 命令。此命令向 /var/lib/net-snmp/snmpd.conf/etc/snmp/snmpd.conf 文件添加条目,这些文件创建用户并为用户授予访问权限。请注意,net-snmp-create-v3-user 命令只能在代理未运行时运行。以下示例创建"admin"用户,其密码为 "redhatsnmp:

~]# systemctl stop snmpd.service
~]# net-snmp-create-v3-user
Enter a SNMPv3 user name to create:
admin
Enter authentication pass-phrase:
redhatsnmp
Enter encryption pass-phrase:
 [press return to reuse the authentication pass-phrase]

adding the following line to /var/lib/net-snmp/snmpd.conf:
  createUser admin MD5 "redhatsnmp" DES
adding the following line to /etc/snmp/snmpd.conf:
  rwuser admin
~]# systemctl start snmpd.service

rwuser 指令(或者提供 -ro 命令行选项时 rouser ),net -snmp-create-v3-user 添加到 /etc/snmp/snmpd.conf 具有与 rwcommunity 和 rocommunity 指令类似的格式:

directive user noauth|auth|priv OID

… 其中 user 是用户名,OID 是 SNMP 树,用于提供对.默认情况下,Net-SNMP 代理守护进程仅允许经过身份验证的请求( auth 选项)。noauth 选项允许您允许未经身份验证的请求,而 priv 选项则强制使用加密。authpriv 选项指定请求必须经过身份验证并且应加密回复。

例如,以下行授予用户"admin"对整个树的读写访问权限:

rwuser admin authpriv .1

要测试配置,请在用户的主目录中创建一个 .snmp/ 目录,并在该目录中创建一个名为 snmp.conf 的配置文件(~/.snmp/snmp.conf):

defVersion 3
defSecurityLevel authPriv
defSecurityName admin
defPassphrase redhatsnmp

现在,在查询代理时,s nmpwalk 命令将使用这些身份验证设置:

~]$ snmpwalk -v3 localhost system
SNMPv2-MIB::sysDescr.0 = STRING: Linux localhost.localdomain 3.10.0-123.el7.x86_64 #1 SMP Mon May 5 11:16:57 EDT 2014 x86_64
[output truncated]

21.7.4. 通过 SNMP 检索性能数据

红帽企业 Linux 中的 Net-SNMP 代理通过 SNMP 协议提供各种性能信息。此外,可以查询代理查找系统上已安装的 RPM 软件包列表、系统上当前运行的进程的列表或系统的网络配置。

本节概述 SNMP 上可用的与性能调优相关的 OID。它假定已安装 net-snmp-utils 软件包,并授予该用户 SNMP 树的访问权限,如 第 21.7.3.2 节 “配置身份验证” 所述。

21.7.4.1. 硬件配置

Net-SNMP 中包含 的主机资源 MIB 提供了有关主机当前硬件和软件配置到客户端实用程序的信息。表 21.3 “可用 OID” 总结了该 MIB 下提供的不同 OID。

表 21.3. 可用 OID

OID描述

HOST-RESOURCES-MIB::hrSystem

包含常规系统信息,如正常运行时间、用户数和运行的进程数。

HOST-RESOURCES-MIB::hrStorage

包含有关内存和文件系统使用情况的数据。

HOST-RESOURCES-MIB::hrDevices

包含所有处理器、网络设备和文件系统的列表。

HOST-RESOURCES-MIB::hrSWRun

包含所有正在运行的进程的列表。

HOST-RESOURCES-MIB::hrSWRunPerf

包含 HOST-RESOURCES-MIB::hrSWRun 进程表的内存和 CPU 统计信息。

HOST-RESOURCES-MIB::hrSWInstalled

包含 RPM 数据库的列表。

主机资源 MIB 中也提供了多个 SNMP 表,可用于检索可用信息的摘要。以下示例显示 HOST-RESOURCES-MIB::hrFSTable:

~]$ snmptable -Cb localhost HOST-RESOURCES-MIB::hrFSTable
SNMP table: HOST-RESOURCES-MIB::hrFSTable

 Index MountPoint RemoteMountPoint                Type
  Access Bootable StorageIndex LastFullBackupDate LastPartialBackupDate
   1    "/"        "" HOST-RESOURCES-TYPES::hrFSLinuxExt2
 readWrite   true      31   0-1-1,0:0:0.0     0-1-1,0:0:0.0
   5 "/dev/shm"        ""   HOST-RESOURCES-TYPES::hrFSOther
 readWrite  false      35   0-1-1,0:0:0.0     0-1-1,0:0:0.0
   6  "/boot"        "" HOST-RESOURCES-TYPES::hrFSLinuxExt2
 readWrite  false      36   0-1-1,0:0:0.0     0-1-1,0:0:0.0

有关 HOST-RESOURCES-MIB 的更多信息,请参阅 /usr/share/snmp/mibs/HOST-RESOURCES-MIB.txt 文件。

21.7.4.2. CPU 和内存信息

大多数系统性能数据在 UCD SNMP MIB 中可用。systemStats OID 围绕处理器使用情况提供多个计数器:

~]$ snmpwalk localhost UCD-SNMP-MIB::systemStats
UCD-SNMP-MIB::ssIndex.0 = INTEGER: 1
UCD-SNMP-MIB::ssErrorName.0 = STRING: systemStats
UCD-SNMP-MIB::ssSwapIn.0 = INTEGER: 0 kB
UCD-SNMP-MIB::ssSwapOut.0 = INTEGER: 0 kB
UCD-SNMP-MIB::ssIOSent.0 = INTEGER: 0 blocks/s
UCD-SNMP-MIB::ssIOReceive.0 = INTEGER: 0 blocks/s
UCD-SNMP-MIB::ssSysInterrupts.0 = INTEGER: 29 interrupts/s
UCD-SNMP-MIB::ssSysContext.0 = INTEGER: 18 switches/s
UCD-SNMP-MIB::ssCpuUser.0 = INTEGER: 0
UCD-SNMP-MIB::ssCpuSystem.0 = INTEGER: 0
UCD-SNMP-MIB::ssCpuIdle.0 = INTEGER: 99
UCD-SNMP-MIB::ssCpuRawUser.0 = Counter32: 2278
UCD-SNMP-MIB::ssCpuRawNice.0 = Counter32: 1395
UCD-SNMP-MIB::ssCpuRawSystem.0 = Counter32: 6826
UCD-SNMP-MIB::ssCpuRawIdle.0 = Counter32: 3383736
UCD-SNMP-MIB::ssCpuRawWait.0 = Counter32: 7629
UCD-SNMP-MIB::ssCpuRawKernel.0 = Counter32: 0
UCD-SNMP-MIB::ssCpuRawInterrupt.0 = Counter32: 434
UCD-SNMP-MIB::ssIORawSent.0 = Counter32: 266770
UCD-SNMP-MIB::ssIORawReceived.0 = Counter32: 427302
UCD-SNMP-MIB::ssRawInterrupts.0 = Counter32: 743442
UCD-SNMP-MIB::ssRawContexts.0 = Counter32: 718557
UCD-SNMP-MIB::ssCpuRawSoftIRQ.0 = Counter32: 128
UCD-SNMP-MIB::ssRawSwapIn.0 = Counter32: 0
UCD-SNMP-MIB::ssRawSwapOut.0 = Counter32: 0

特别是,ssCpuRawUserssCpuRawSystemssCpuRawWaitssCpuRawIdle OID 提供计数器,它们有助于确定系统是否在内核空间、用户空间或 I/O 中消耗大部分处理器时间。ssRawSwapInssRawSwapOut 在确定系统是否存在内存耗尽时非常有用。

UCD-SNMP-MIB::memory OID 下提供了更多内存信息,它提供与 可用 命令类似的数据:

~]$ snmpwalk localhost UCD-SNMP-MIB::memory
UCD-SNMP-MIB::memIndex.0 = INTEGER: 0
UCD-SNMP-MIB::memErrorName.0 = STRING: swap
UCD-SNMP-MIB::memTotalSwap.0 = INTEGER: 1023992 kB
UCD-SNMP-MIB::memAvailSwap.0 = INTEGER: 1023992 kB
UCD-SNMP-MIB::memTotalReal.0 = INTEGER: 1021588 kB
UCD-SNMP-MIB::memAvailReal.0 = INTEGER: 634260 kB
UCD-SNMP-MIB::memTotalFree.0 = INTEGER: 1658252 kB
UCD-SNMP-MIB::memMinimumSwap.0 = INTEGER: 16000 kB
UCD-SNMP-MIB::memBuffer.0 = INTEGER: 30760 kB
UCD-SNMP-MIB::memCached.0 = INTEGER: 216200 kB
UCD-SNMP-MIB::memSwapError.0 = INTEGER: noError(0)
UCD-SNMP-MIB::memSwapErrorMsg.0 = STRING:

UCD SNMP MIB 中 也提供负载平均值。SNMP 表 UCD-SNMP-MIB::laTable 包含 1、5 和 15 分钟负载平均值列表:

~]$ snmptable localhost UCD-SNMP-MIB::laTable
SNMP table: UCD-SNMP-MIB::laTable

 laIndex laNames laLoad laConfig laLoadInt laLoadFloat laErrorFlag laErrMessage
    1 Load-1  0.00  12.00     0  0.000000   noError
    2 Load-5  0.00  12.00     0  0.000000   noError
    3 Load-15  0.00  12.00     0  0.000000   noError

21.7.4.3. 文件系统和磁盘信息

主机资源 MIB 提供有关文件系统大小和使用情况的信息。每个文件系统(以及每个内存池)在 HOST-RESOURCES-MIB::hrStorageTable 表中都有一个条目:

~]$ snmptable -Cb localhost HOST-RESOURCES-MIB::hrStorageTable
SNMP table: HOST-RESOURCES-MIB::hrStorageTable

 Index                     Type      Descr
AllocationUnits  Size  Used AllocationFailures
   1      HOST-RESOURCES-TYPES::hrStorageRam Physical memory
1024 Bytes 1021588 388064         ?
   3 HOST-RESOURCES-TYPES::hrStorageVirtualMemory Virtual memory
1024 Bytes 2045580 388064         ?
   6     HOST-RESOURCES-TYPES::hrStorageOther Memory buffers
1024 Bytes 1021588 31048         ?
   7     HOST-RESOURCES-TYPES::hrStorageOther  Cached memory
1024 Bytes 216604 216604         ?
  10 HOST-RESOURCES-TYPES::hrStorageVirtualMemory   Swap space
1024 Bytes 1023992   0         ?
  31   HOST-RESOURCES-TYPES::hrStorageFixedDisk        /
4096 Bytes 2277614 250391         ?
  35   HOST-RESOURCES-TYPES::hrStorageFixedDisk    /dev/shm
4096 Bytes 127698   0         ?
  36   HOST-RESOURCES-TYPES::hrStorageFixedDisk      /boot
1024 Bytes 198337 26694         ?

HOST-RESOURCES-MIB::hrStorageSizeHOST-RESOURCES-MIB::hrStorageUsed 下的 OID 可以用来计算每个挂载的文件系统的剩余容量。

UCD-SNMP-MIB::systemStats(ss IORawSent.0 和 ssIORawRecieved.0 )和 UCD-DISKIO-MIB::diskIOTable 中都可以使用 I/O 数据。后者提供了更精细的数据。在此表中是 diskIONReadXdiskIONWrittenX 的 OID,它们为系统引导后读取并写入块设备的字节数提供计数器:

~]$ snmptable -Cb localhost UCD-DISKIO-MIB::diskIOTable
SNMP table: UCD-DISKIO-MIB::diskIOTable

 Index Device   NRead NWritten Reads Writes LA1 LA5 LA15  NReadX NWrittenX
...
  25  sda 216886272 139109376 16409  4894  ?  ?  ? 216886272 139109376
  26  sda1  2455552   5120  613   2  ?  ?  ?  2455552   5120
  27  sda2  1486848     0  332   0  ?  ?  ?  1486848     0
  28  sda3 212321280 139104256 15312  4871  ?  ?  ? 212321280 139104256

21.7.4.4. 网络信息

Interfaces MIB 提供有关网络设备的信息。IF-MIB::ifTable 提供 SNMP 表,其中包含系统上每个接口的条目、接口的配置以及接口的各种数据包计数器。以下示例显示了在有两个物理网络接口的系统中 ifTable 的前几列:

~]$ snmptable -Cb localhost IF-MIB::ifTable
SNMP table: IF-MIB::ifTable

 Index Descr       Type  Mtu  Speed   PhysAddress AdminStatus
   1  lo softwareLoopback 16436 10000000              up
   2 eth0  ethernetCsmacd 1500    0 52:54:0:c7:69:58     up
   3 eth1  ethernetCsmacd 1500    0 52:54:0:a7:a3:24    down

网络流量位于 OIDs IF-MIB::ifOutOctetsIF-MIB::ifInOctets 下。以下 SNMP 查询将检索此系统中每个接口的网络流量:

~]$ snmpwalk localhost IF-MIB::ifDescr
IF-MIB::ifDescr.1 = STRING: lo
IF-MIB::ifDescr.2 = STRING: eth0
IF-MIB::ifDescr.3 = STRING: eth1
~]$ snmpwalk localhost IF-MIB::ifOutOctets
IF-MIB::ifOutOctets.1 = Counter32: 10060699
IF-MIB::ifOutOctets.2 = Counter32: 650
IF-MIB::ifOutOctets.3 = Counter32: 0
~]$ snmpwalk localhost IF-MIB::ifInOctets
IF-MIB::ifInOctets.1 = Counter32: 10060699
IF-MIB::ifInOctets.2 = Counter32: 78650
IF-MIB::ifInOctets.3 = Counter32: 0

21.7.5. 扩展 Net-SNMP

可以扩展 Net-SNMP 代理,以提供除原始系统指标外的应用指标。这可实现容量规划以及性能问题故障排除。例如,了解电子邮件系统的负载平均值为 15 分钟,而测试期间的负载平均值为 15,但知道电子邮件系统的负载平均值为 15 次,处理第 15 条消息会很有帮助。当应用程序指标通过与系统指标相同的接口获得时,也可以视觉化了解不同负载场景对系统性能的影响(例如,每条额外的 10,000 个消息都会线性增大负载平均值到 100,000)。

红帽企业 Linux 中包含的许多应用程序扩展了 Net-SNMP 代理,以通过 SNMP 提供应用指标。另外,也可以为自定义应用程序扩展代理。本节论述了使用 shell 脚本和可选频道中的 Perl 插件扩展代理。它假设安装了 net-snmp-utilsnet-snmp-perl 软件包,并授予该用户对 SNMP 树的访问权限,如 第 21.7.3.2 节 “配置身份验证” 所述。

21.7.5.1. 使用 Shell 脚本扩展 Net-SNMP

Net-SNMP 代理提供一个扩展 MIB(NET-SNMP-EXTEND-MIB),可用于查询任意 shell 脚本。要指定要运行的 shell 脚本,请使用 /etc/snmp/snmpd.conf 文件中的 extend 指令。定义后,代理将通过 SNMP 提供 命令的退出代码和任何输出。以下示例通过脚本演示此机制,此脚本决定了进程表中的 httpd 进程数。

注意

Net-SNMP 代理还提供内置机制,用于通过 proc 指令检查流程表。如需更多信息,请参阅 snmpd.conf(5)手册页。

以下 shell 脚本的退出代码是在给定时间点运行在系统上运行的 httpd 进程数:

#!/bin/sh

NUMPIDS=pgrep httpd | wc -l

exit $NUMPIDS

要使该脚本可通过 SNMP 使用,请将 脚本复制到系统路径上的位置,设置可执行位,并将 扩展 指令添加到 /etc/snmp/snmpd.conf 文件。扩展 指令的格式如下:

extend name prog args

… 其中 name 是扩展的标识字符串,prog 是要运行的程序,args 则是提供程序的参数。例如,如果将上述 shell 脚本复制到 /usr/local/bin/check_apache.sh 中,以下指令会将脚本添加到 SNMP 树中:

extend httpd_pids /bin/sh /usr/local/bin/check_apache.sh

然后,可以在 NET-SNMP-EXTEND-MIB::nsExtendObjects 中 查询该脚本:

~]$ snmpwalk localhost NET-SNMP-EXTEND-MIB::nsExtendObjects
NET-SNMP-EXTEND-MIB::nsExtendNumEntries.0 = INTEGER: 1
NET-SNMP-EXTEND-MIB::nsExtendCommand."httpd_pids" = STRING: /bin/sh
NET-SNMP-EXTEND-MIB::nsExtendArgs."httpd_pids" = STRING: /usr/local/bin/check_apache.sh
NET-SNMP-EXTEND-MIB::nsExtendInput."httpd_pids" = STRING:
NET-SNMP-EXTEND-MIB::nsExtendCacheTime."httpd_pids" = INTEGER: 5
NET-SNMP-EXTEND-MIB::nsExtendExecType."httpd_pids" = INTEGER: exec(1)
NET-SNMP-EXTEND-MIB::nsExtendRunType."httpd_pids" = INTEGER: run-on-read(1)
NET-SNMP-EXTEND-MIB::nsExtendStorage."httpd_pids" = INTEGER: permanent(4)
NET-SNMP-EXTEND-MIB::nsExtendStatus."httpd_pids" = INTEGER: active(1)
NET-SNMP-EXTEND-MIB::nsExtendOutput1Line."httpd_pids" = STRING:
NET-SNMP-EXTEND-MIB::nsExtendOutputFull."httpd_pids" = STRING:
NET-SNMP-EXTEND-MIB::nsExtendOutNumLines."httpd_pids" = INTEGER: 1
NET-SNMP-EXTEND-MIB::nsExtendResult."httpd_pids" = INTEGER: 8
NET-SNMP-EXTEND-MIB::nsExtendOutLine."httpd_pids".1 = STRING:

请注意,退出代码(本示例中为"8")作为 INTEGER 类型提供,任何输出都以 STRING 类型提供。若要以整数形式公开多个指标,请使用 extend 指令向 脚本提供不同的参数。例如,以下 shell 脚本可用于确定匹配任意字符串的进程数量,同时还会输出一个文本字符串,给出的进程数量:

#!/bin/sh

PATTERN=$1
NUMPIDS=pgrep $PATTERN | wc -l

echo "There are $NUMPIDS $PATTERN processes."
exit $NUMPIDS

当以上脚本复制到 / usr/local/bin/proc.sh 时,以下 /etc/ s nmpd.conf 指令将同时提供 httpd PID 的数量以及 snmpd PID 的数量:

extend httpd_pids /bin/sh /usr/local/bin/check_proc.sh httpd
extend snmpd_pids /bin/sh /usr/local/bin/check_proc.sh snmpd

以下示例显示了 then sExtendObjects OID 的 snmpwalk 的输出结果:

~]$ snmpwalk localhost NET-SNMP-EXTEND-MIB::nsExtendObjects
NET-SNMP-EXTEND-MIB::nsExtendNumEntries.0 = INTEGER: 2
NET-SNMP-EXTEND-MIB::nsExtendCommand."httpd_pids" = STRING: /bin/sh
NET-SNMP-EXTEND-MIB::nsExtendCommand."snmpd_pids" = STRING: /bin/sh
NET-SNMP-EXTEND-MIB::nsExtendArgs."httpd_pids" = STRING: /usr/local/bin/check_proc.sh httpd
NET-SNMP-EXTEND-MIB::nsExtendArgs."snmpd_pids" = STRING: /usr/local/bin/check_proc.sh snmpd
NET-SNMP-EXTEND-MIB::nsExtendInput."httpd_pids" = STRING:
NET-SNMP-EXTEND-MIB::nsExtendInput."snmpd_pids" = STRING:
...
NET-SNMP-EXTEND-MIB::nsExtendResult."httpd_pids" = INTEGER: 8
NET-SNMP-EXTEND-MIB::nsExtendResult."snmpd_pids" = INTEGER: 1
NET-SNMP-EXTEND-MIB::nsExtendOutLine."httpd_pids".1 = STRING: There are 8 httpd processes.
NET-SNMP-EXTEND-MIB::nsExtendOutLine."snmpd_pids".1 = STRING: There are 1 snmpd processes.
警告

整数退出代码限制为 0-255 范围。对于可能超过 256 的值,请使用脚本的标准输出(将键入为字符串)或不同的扩展代理方法。

最后一个示例显示了对系统的可用内存和 httpd 进程数量的查询。此查询可用于性能测试,以确定进程数量对内存压力的影响:

~]$ snmpget localhost \
  'NET-SNMP-EXTEND-MIB::nsExtendResult."httpd_pids"' \
  UCD-SNMP-MIB::memAvailReal.0
NET-SNMP-EXTEND-MIB::nsExtendResult."httpd_pids" = INTEGER: 8
UCD-SNMP-MIB::memAvailReal.0 = INTEGER: 799664 kB

21.7.5.2. 使用 Perl 扩展 Net-SNMP

使用 extend 指令执行 shell 脚本是一种相当受限的方法,用于通过 SNMP 公开自定义应用指标。Net-SNMP 代理还提供嵌入式 Perl 接口来公开自定义对象。Optional 频道中的 net-snmp-perl 软件包提供 NetSNMP::agent Perl 模块,用于在 Red Hat Enterprise Linux 中编写嵌入式 Perl 插件。

NetSNMP::agent Perl 模块提供了一个 代理 对象,用于处理代理 OID 树的一部分的请求。agent 对象的构造器具有作为 snmpd 或独立代理的子代理运行代理的选项。创建嵌入式代理不需要任何参数:

use NetSNMP::agent (':all');

my $agent = new NetSNMP::agent();

代理 对象具有一个 寄存器 方法,用于使用特定的 OID 注册回调函数。register 函数将名称 OID 和指针用于回调函数。以下示例将使用 SNMP Agent 注册名为 hello_handler 的回调函数,该代理将处理 OID .1.3.6.1.4.1.8072.9999.9999 下的请求:

$agent->register("hello_world", ".1.3.6.1.4.1.8072.9999.9999",
         \&hello_handler);
注意

OID .1.3.6.1.4.1.8072.9999.9999 (NET-SNMP-MIB::netSnmpPlaypen)通常仅用于演示目的。如果您的组织还没有根 OID,可以通过联系美国 ISO 名称注册机构(ANSI)来获取一个。

该处理程序功能将通过四个参数调用: HANDLERREGISTRATION_INFO、REQUEST_INFOREQUESTSREQUESTS 参数包含当前调用中的请求列表,应迭代并使用数据填充。列表中 的请求 对象具有 get 和 set 方法,允许操作请求的 OID。例如,以下调用会将请求对象的值设置为字符串 "hello world":

$request->setValue(ASN_OCTET_STR, "hello world");

处理程序函数应响应两种类型的 SNMP 请求:GET 请求和 GETNEXT 请求。请求类型通过调用作为第三个参数传递给处理程序函数的 request_info 对象的 getMode 方法来确定。如果请求是 GET 请求,调用者将预期处理程序设置 请求 对象 的值,具体取决于请求的 OID。如果请求是 GETNEXT 请求,调用者还将请求的 OID 设置为树中下一个可用的 OID。下面的代码示例演示了这种情况:

my $request;
my $string_value = "hello world";
my $integer_value = "8675309";

for($request = $requests; $request; $request = $request->next()) {
 my $oid = $request->getOID();
 if ($request_info->getMode() == MODE_GET) {
  if ($oid == new NetSNMP::OID(".1.3.6.1.4.1.8072.9999.9999.1.0")) {
   $request->setValue(ASN_OCTET_STR, $string_value);
  }
  elsif ($oid == new NetSNMP::OID(".1.3.6.1.4.1.8072.9999.9999.1.1")) {
   $request->setValue(ASN_INTEGER, $integer_value);
  }
 } elsif ($request_info->getMode() == MODE_GETNEXT) {
  if ($oid == new NetSNMP::OID(".1.3.6.1.4.1.8072.9999.9999.1.0")) {
   $request->setOID(".1.3.6.1.4.1.8072.9999.9999.1.1");
   $request->setValue(ASN_INTEGER, $integer_value);
  }
  elsif ($oid < new NetSNMP::OID(".1.3.6.1.4.1.8072.9999.9999.1.0")) {
   $request->setOID(".1.3.6.1.4.1.8072.9999.9999.1.0");
   $request->setValue(ASN_OCTET_STR, $string_value);
  }
 }
}

getMode 返回 MODE_GET 时,处理程序会分析 请求 对象上 getOID 调用的值。如果 OID 以 ".1.0" 结束,请求 的值 将设为 string_value,如果 OID 以 ".1.1" 结束,则设置为 integer_value。如果 getMode 返回 MODE_GETNEXT,处理程序将决定请求的 OID 是否为 ".1.0",然后设置 OID 和值 ".1.1"。如果树上的请求高于 ".1.0",则设置了 ".1.0" 的 OID 和值。实际上,这将返回树中的"下一步"值,以便 snmpwalk 等程序可以遍历树,而不必事先了解结构。

变量的类型使用 NetSNMP::ASN 中的 常量来设置。有关可用常数的完整列表,请参阅 NetSNMP::ASNperldoc

这个示例 Perl 插件的完整代码列表如下:

#!/usr/bin/perl

use NetSNMP::agent (':all');
use NetSNMP::ASN qw(ASN_OCTET_STR ASN_INTEGER);

sub hello_handler {
 my ($handler, $registration_info, $request_info, $requests) = @_;
 my $request;
 my $string_value = "hello world";
 my $integer_value = "8675309";

 for($request = $requests; $request; $request = $request->next()) {
  my $oid = $request->getOID();
  if ($request_info->getMode() == MODE_GET) {
   if ($oid == new NetSNMP::OID(".1.3.6.1.4.1.8072.9999.9999.1.0")) {
    $request->setValue(ASN_OCTET_STR, $string_value);
   }
   elsif ($oid == new NetSNMP::OID(".1.3.6.1.4.1.8072.9999.9999.1.1")) {
    $request->setValue(ASN_INTEGER, $integer_value);
   }
  } elsif ($request_info->getMode() == MODE_GETNEXT) {
   if ($oid == new NetSNMP::OID(".1.3.6.1.4.1.8072.9999.9999.1.0")) {
    $request->setOID(".1.3.6.1.4.1.8072.9999.9999.1.1");
    $request->setValue(ASN_INTEGER, $integer_value);
   }
   elsif ($oid < new NetSNMP::OID(".1.3.6.1.4.1.8072.9999.9999.1.0")) {
    $request->setOID(".1.3.6.1.4.1.8072.9999.9999.1.0");
    $request->setValue(ASN_OCTET_STR, $string_value);
   }
  }
 }
}

my $agent = new NetSNMP::agent();
$agent->register("hello_world", ".1.3.6.1.4.1.8072.9999.9999",
         \&hello_handler);

要测试插件,请将上述程序复制到 /usr/share/snmp/hello_world.pl,并将以下行添加到 /etc/snmp/snmpd.conf 配置文件:

perl do "/usr/share/snmp/hello_world.pl"

需要重启 SNMP 代理守护进程来加载新的 Perl 插件。重启后,s nmpwalk 应该返回新数据:

~]$ snmpwalk localhost NET-SNMP-MIB::netSnmpPlaypen
NET-SNMP-MIB::netSnmpPlaypen.1.0 = STRING: "hello world"
NET-SNMP-MIB::netSnmpPlaypen.1.1 = INTEGER: 8675309

snmpget 也应用于操作处理程序的其他模式:

~]$ snmpget localhost \
  NET-SNMP-MIB::netSnmpPlaypen.1.0 \
  NET-SNMP-MIB::netSnmpPlaypen.1.1
NET-SNMP-MIB::netSnmpPlaypen.1.0 = STRING: "hello world"
NET-SNMP-MIB::netSnmpPlaypen.1.1 = INTEGER: 8675309