[comment]: # aside:4

[comment]: # ({ded6a8cd-ebcec779})
# 从 Zabbix agent 收集数据

[comment]: # ({/ded6a8cd-ebcec779})

[comment]: # ({1640c1a8-02f6ab0d})
#### 概述

[zabbix\_utils](https://github.com/zabbix/python-zabbix-utils/blob/main/README.md) 允许您从 Zabbix agent 收集数据（类似于 [Zabbix get](/manual/concepts/get)）。

可以使用同步或异步模式收集数据：

-   在同步模式下，您的 Python 脚本会先请求并等待数据返回，然后再继续执行，这适用于简单、顺序性强且可预测的操作。
-   在异步模式下，脚本发出数据请求后不会等待每个响应返回，从而允许其他操作并行进行；对于响应较慢的请求或大批量数据，这种方式效率更高。

本页中的示例主要侧重于同步模式，不过[异步模式](#asynchronous-mode)也遵循类似的模式。
更多示例可在 GitHub 仓库中的 [zabbix_utils](https://github.com/zabbix/python-zabbix-utils/tree/main/examples) 中找到。

[comment]: # ({/1640c1a8-02f6ab0d})

[comment]: # ({d16d4df7-8b91e8b3})
#### 导入

要使用 zabbix\_utils 收集监控项值，请在您的 Python 脚本中导入 `Getter` 类：

```python
from zabbix_utils import Getter
```

[comment]: # ({/d16d4df7-8b91e8b3})

[comment]: # ({fc153113-7e0dc385})
#### 请求数据

要请求监控项值：

1. 创建一个 `Getter` 实例，指定 Zabbix agent 的 IP 地址和端口。
2. 在 `Getter` 实例上调用 `get()` 方法，指定要检索的监控项键值。

例如，要请求 `system.uname` 监控项的数据：

```python
agent = Getter(host='192.0.2.1', port=10050)
response = agent.get('system.uname')
```

[comment]: # ({/fc153113-7e0dc385})

[comment]: # ({2551b53a-b5e0ad53})
##### 使用非默认 IP

如果运行脚本的服务器有多个 IP 地址，您可以为 `Getter` 指定一个 `source_ip`，以便在连接到 Zabbix agent 时使用：

```python
agent = Getter(
    host='192.0.2.1',
    port=10050,
    source_ip='10.10.7.1'
)
```

[comment]: # ({/2551b53a-b5e0ad53})

[comment]: # ({e0779036-6bc440d9})
##### 使用超时

您可以为 `Getter` 设置响应 `timeout`，以控制脚本在放弃之前应等待 Zabbix agent 响应的时间：

```python
agent = Getter(
    host='192.0.2.1',
    port=10050,
    timeout=30
)
```

[comment]: # ({/e0779036-6bc440d9})

[comment]: # ({bd31e71c-6a0fc829})
##### 使用加密

`Getter` 不包含内置加密支持，但你可以通过使用第三方库创建一个包装器来提供它：

```python
def psk_wrapper(sock, tls):
    # ...
    # socket 的 TLS PSK 包装器实现
    # ...

agent = Getter(
    host='192.0.2.1',
    port=10050,
    socket_wrapper=psk_wrapper
)
```

[comment]: # ({/bd31e71c-6a0fc829})

[comment]: # ({4eff4d20-9556e19b})
##### 响应

来自 Zabbix agent 的响应由库处理，并作为 `AgentResponse` 对象返回：

```python
print(response)
# {
#     "error": null,
#     "raw": "Linux zabbix_server 5.15.0-3.60.5.1.el9uek.x86_64",
#     "value": "Linux zabbix_server 5.15.0-3.60.5.1.el9uek.x86_64"
# }

print(response.value)
# Linux zabbix_server 5.15.0-3.60.5.1.el9uek.x86_64

print(response.error)
# None
```

[comment]: # ({/4eff4d20-9556e19b})

[comment]: # ({ab16eafa-abc52038})
##### 异步模式

异步模式允许你的脚本在不等待每个值返回的情况下收集值。
当脚本需要收集大量值，或者某些值的收集耗时较长时，这可以让脚本更高效。

使用异步模式时，与同步模式相比有一些重要区别：

-   导入 Python 的 `asyncio` 模块（你必须先[安装](/devel/python/install)所需依赖）。
-   导入 `AsyncGetter`，而不是 `Getter`。
-   将代码写在 `async` 函数中。
-   调用 `get()` 方法时使用 `await`。

例如，要使用异步模式收集单个值：

```python
# 1. 为异步模式导入 asyncio，并从 zabbix_utils 导入 AsyncGetter：
import asyncio
from zabbix_utils import AsyncGetter

# 2. 定义主 async 函数，所有数据请求都将在其中执行：
async def main():
    agent = AsyncGetter(host='192.0.2.1', port=10050)

    # 3. 从 Zabbix agent 获取 system.uname 值（必须使用 await）：
    response = await agent.get('system.uname')

    # 4. 打印 Zabbix agent 返回的值：
    print(response.value)

# 5. 使用 asyncio 的事件循环运行 async main() 函数：
asyncio.run(main())
```

[comment]: # ({/ab16eafa-abc52038})
