# 2 SNMP代理

#### 概述

你可能希望在启用SNMP的设备（如打印机、交换机、路由器或UPS）上使用SNMP监控，因为在这些设备上尝试安装完整的操作系统和Zabbix代理是不可能的。

为了能够监控SNMP代理在这些设备上提供的数据，Zabbix服务器[初始化配置](/zh/manual/installation/install#configure_the_sources)时必须具有SNMP支持。

仅通过UDP协议执行SNMP检查。

从Zabbix
2.2.3开始，Zabbix服务器和代理守护进程在单个请求中查询多个值的SNMP设备。这会影响各种SNMP监控项（常规SNMP项目，具有动态索引的SNMP项目和SNMP低级别发现），它使SNMP处理更加高效。
请参阅下面的[技术细节部分](#internal_workings_of_bulk_processing)，了解内部工作原理。
从Zabbix
2.4开始，它还为每个接口提供了一个“使用批量请求”的设置，允许为无法正确处理它们的设备禁用批量请求。

从Zabbix 2.2.7和Zabbix
2.4.2开始，Zabbix服务器和代理守护程序的日志在收到不正确的SNMP响应时会打印类似以下内容：`SNMP response from host "gateway" does not contain all of the requested variable bindings`虽然它们没有涵盖所有有问题的情况，但它们对于识别应禁用批量请求的各个SNMP设备非常有用。

从Zabbix
2.2开始Zabbix服务器和代理守护程序在执行SNMP检查时使用对应的超时配置参数。另外，在单个不成功的SNMP请求（超时/错误凭据）之后，守护程序不执行重试。之前，实际使用了SNMP库默认超时和重试值（分别为1秒和5次重试）。

从Zabbix 2.2.8和Zabbix
2.4.2开始，Zabbix服务器和代理守护程序将始终至少重试一次：通过SNMP库的重试机制或通过[内部批量处理机制](#internal_workings_of_bulk_processing)。

<note
warning>如果监控SNMPv3设备，请确保msgAuthoritativeEngineID（也称为snmpEngineID或“引擎ID”）从不被两台设备共享。根据[RFC
2571](http://www.ietf.org/rfc/rfc2571.txt)
（3.1.1.1节），每个设备必须是唯一的。
:::

#### 配置SNMP监控

要通过SNMP开始监控设备，必须执行以下步骤：

##### 步骤 1

使用SNMP接口为设备[创建一个主机](/zh/manual/config/hosts/host)。

输入IP地址。你可以使用自动添加一套监控项提供的SNMP模板之一（*SNMP设备模板*等）。但是，模板可能与主机不兼容。
单击 *Add* 以保存主机。

::: notetip
SNMP检查不使用 *代理端口*, 请忽略它。
:::

##### 步骤 2

找出要监控项目的SNMP字符串（或OID）。

要获取SNMP字符串列表，请使用 **snmpwalk**
命令（[net-snmp](http://www.net-snmp.org/)的部分软件应该在Zabbix安装时同时安装）或等效工具：

    shell> snmpwalk -v 2c -c public <host IP> .

这里的'2c'代表SNMP版本，你也可以将其替换为'1'，以在设备上指定SNMP版本为v1。

它会返回给你一个SNMP字符串及其最后一个值的列表。如果不是，那么SNMP
'community' 可能与标准的'public'不同，在这种情况下，请找出它是什么。

然后，你可以浏览列表，直到找到要监控的字符串，例如：如果要监视通过端口3进入交换机的字节，你将使用此行中的`IF-MIB :: ifInOctets.3`字符串：

    IF-MIB::ifInOctets.3 = Counter32: 3409739121

你现在可以使用 **snmpget** 命令找出'IF-MIB :: ifInOctets.3'的数字OID：

    shell> snmpget -v 2c -c public -On 10.62.1.22 IF-MIB::ifInOctets.3

请注意，字符串中的最后一个数字是你要监控的端口号。请参考:
[动态索引](/zh/manual/config/items/itemtypes/snmp/dynamicindex).

如下所示：

    .1.3.6.1.2.1.2.2.1.10.3 = Counter32: 3472126941

重复一遍，OID中的最后一个号码是端口号。

::: noteclassic
3COM似乎是使用数百个端口号，例如
端口1=端口101，端口3=端口103，但思科使用常规数字，例如。
端口3=3。
:::

::: notetip
一些最常用的SNMP
OID，Zabbix将[自动转换为数字表示](/zh/manual/config/items/itemtypes/snmp/special_mibs)。
:::

在上面的例子中，值类型是“Counter32”它在内部对应于ASN\_COUNTER类型。完整的支持类型包括
ASN\_COUNTER, ASN\_COUNTER64, ASN\_UINTEGER, ASN\_UNSIGNED64,
ASN\_INTEGER, ASN\_INTEGER64, ASN\_FLOAT, ASN\_DOUBLE, ASN\_TIMETICKS,
ASN\_GAUGE, ASN\_IPADDRESS, ASN\_OCTET\_STR 和 ASN\_OBJECT\_ID (从2.2.8,
2.4.3之后). 这些类型大致对应于**snmpget** 输出的 "Counter32",
"Counter64", "UInteger32", "INTEGER", "Float", "Double", "Timeticks",
"Gauge32", "IpAddress", "OCTET STRING", "OBJECT IDENTIFIER",
但也有可能显示为 "STRING", "Hex-STRING", "OID" 或者其它,
这取这取决于显示提示的表达方式。

##### 步骤 3

创建一个监控项。

所以现在回到Zabbix并点击前面创建的SNMP主机的 *监控项* 。
如果你在创建主机时选择使用模板，你将拥有与主机相关联的SNMP监控项列表。我们假设你要使用snmpwalk和snmpget采集的信息创建监控项，单击
*创建监控项*。在新的监控项表单中，输入监控项“名称”。确保“主机接口”字段中有你的交换机/路由器，并将"类型"字段更改为"SNMPv\*
客户端"。 输入community
（通常是public），并将你之前检索到的文本或数字OID输入到'SNMP
OID'字段中，例如：.1.3.6.1.2.1.2.2.1.10.3

输入SNMP“端口”为161，“键值”为有意义的内容，例如，SNMP-InOctets-Bps。将“信息类型”设置为
*浮点数* ，并在进程预定步骤中添加 *每秒更改*
的策略（重要！否则你将从SNMP设备获取累积值，而不是最新的变化）。如果你希望“更新间隔”和“历史数据保留时长”与默认值不同，请选择一个自定义乘数（如果需要），并输入
。

![](../../../../../assets/en/manual/config/items/itemtypes/snmpv3_item.png)
![](../../../../../assets/zh/manual/config/items/itemtypes/snmpv3_item_zh.png)

所有必填输入字段都标有红色星号。

现在保存监控项，进入 *监测中* → *最新数据* 来获取你的SNMP数据!

请注意SNMPv3监控的具体选项：

|参数           描|<|
|--------------------|-|
|*上下文名称*   输入上下|名称以标识SNMP子网上的监控项。<br>从Zabbix 2.2开始SNMPv3监控支持*上下文名称*。<br>用户宏在此字段中解析。|
|*安全名称*     输入安|名称<br>用户宏在此字段中解析。|
|*安全级别*     选择安|级别：<br>**noAuthNoPriv** - 不使用身份验证或隐私协议<br>**AuthNoPriv** - 认证协议被使用，但不使用隐私协议<br>**AuthPriv** - 使用身份验证和隐私协议|
|*验证协议*     选择验|协议 - *MD5* 或者 *SHA*.|
|*验证口令*     输入验|口令。<br>用户宏在此字段中解析。|
|*隐私协议*     选择隐|协议 - *DES* 或者*AES*.|
|*私钥*         输|私钥。<br>用户宏在此字段中解析。|

如果SNMPv3凭据（安全名称，验证协议/口令，隐私协议）错误，Zabbix会从net-snmp收到错误，如果
*私钥* 错误，在这种情况下，Zabbix会从net-snmp收到TIMEOUT错误。

::: notewarning
*验证协议*, *验证口令*, *隐私协议* 或 *私钥*
修改后，需要重启服务器或代理来生效。
:::

##### 示例 1

一般范例：

|参数            描|<|
|---------------------|-|
|**Community**|public|
|**OID**|1.2.3.45.6.7.8.0 (or .1.2.3.45.6.7.8.0)|
|**键值**        &|t;用作触发器引用的唯一字符串><br>例如, "my\_param".|

请注意，OID可以以数字或字符串形式给出。但是，在某些情况下，字符串OID必须转换为数字表示。
snmpget可用于此目的：

在配置Zabbix源时指定了 --with-net-snmp 标志，可以监视SNMP参数。

##### 示例 2

监控正常运行时间：

|Parameter|Description|
|---------|-----------|
|**Community**|public|
|**Oid**|MIB::sysUpTime.0|
|**Key**|router.uptime|
|**Value type**|Float|
|**Units**|uptime|
|**Multiplier**|0.01|

|参数            描|<|
|---------------------|-|
|**Community**|public|
|**OID**|MIB::sysUpTime.0|
|**键值**        r|uter.uptime|
|**信息类型**    浮点数|<|
|**单位**        u|time|
|**乘数**        0|01|

#### 批处理的内部工作

从2.2.3开始Zabbix服务器和代理查询SNMP设备在单个请求中的多个值。这会影响多种类型的SNMP监控项：

-   常规SNMP监控项;
-   [具有动态索引的SNMP监控项](/zh/manual/config/items/itemtypes/snmp/dynamicindex);
-   [SNMP低级发现规则](/zh/manual/discovery/low_level_discovery#discovery_of_snmp_oids).

具有相同参数的单个接口上的所有SNMP监控项都将同时进行查询。前两种类型的监控项由轮询器分批采集，最多128个监控项，而低级发现规则如前所述单独处理。

在较低级别上，执行查询值的操作有两种：获取多个指定对象和游历OID树。

对于"getting"，GetRequest-PDU最多使用128个变量绑定。
对于"walking"，GetNextRequest-PDU用于SNMPv1和GetBulkRequest，"max-repetitions"字段最多128个用于SNMPv2和SNMPv3。

因此，每个SNMP监控项类型的批量处理的优势如下：

      * 常规SNMP项目受益于“getting” 的改进;
      * 具有动态索引的SNMP监控项受益于“getting”和“walking”改进：“getting”用于索引验证，“walking”用于构建缓存;
      * SNMP低级发现规则受益于“walking”的改进。

然而，有一个技术问题，并非所有设备都能够根据请求返回128个值。有些总是给出正确的回应，其它情况则会以“tooBig（1）”错误做出回应，或者一旦潜在的回应超过了一定的限度，则一律不回应。

为了找到最佳数量的对象来查询给定的设备，Zabbix使用以下策略。它在请求中查询“值1”时谨慎开始。
如果成功，它会在请求中查询“值2”。
如果再次成功，则查询请求中的“值3”，并通过将查询对象的数量乘以1.5来继续，导致以下请求大小的顺序：1,2,3,4,6,9,13,19，28，42，63，94，128。

然而，一旦设备拒绝给出适当的响应（例如，对于42个变量），Zabbix会做两件事情。

首先，对于当前批量监控项，它将单个请求中的对象数减半，并查询21个变量。
如果设备处于活动状态，那么查询应该在绝大多数情况下都有效，因为已知28个变量可以工作，21个变量明显少于此。
但是，如果仍然失败，那么Zabbix会逐渐回到查询值。
如果此时仍然失败，那么设备肯定没有响应，请求大小也不是问题。

Zabbix为后续批量监控项做的第二件事是它从最后成功的变量数量开始（在我们的示例中为28），并继续将请求大小递增1，直到达到限制。
例如，假设最大响应大小为32个变量，后续请求的大小为29,30,31,32和33.最后一个请求将失败，Zabbix将永远不再发出大小为33的请求。
从那时起，Zabbix将为该设备查询最多32个变量。

如果大型查询因此数量的变量而失败，则可能意味着两件事之一。
设备用于限制响应大小的确切标准无法知晓，但我们尝试使用变量数来近似。
因此，第一种可能性是，在一般情况下，此数量的变量大约是设备的实际响应大小限制：有时响应小于限制，有时它大于限制。
第二种可能性是任何方向的UDP数据包都丢失了。
由于这些原因，如果Zabbix查询失败，它会减少最大数量的变量以尝试深入到设备的舒适范围，但（从2.2.8开始）最多只能达到两次。

在上面的示例中，如果包含32个变量的查询失败，Zabbix会将计数减少到31.如果发生这种情况也会失败，Zabbix也会将计数减少到30.但是，Zabbix不会将计数减少到30以下，
因为它会假设进一步的失败是由于UDP数据包丢失，而不是设备的限制。

但是，如果设备由于其他原因无法正确处理批量请求，并且上述启发式方法不起作用，Zabbix
2.4之后每个接口都有“使用批量请求”设置，允许禁用该设备的批量请求。
