You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在收到SNMP Set报文时触发脚本执行

核心解决方案:直接捕获SNMP Set请求触发脚本

不用转Trap,直接监听SNMP默认UDP 161端口的Set请求,解析后执行指定脚本,这是最直接高效的方案,下面分平台给出实现:

Windows平台(PowerShell实现)

前置准备

  1. 以管理员身份打开PowerShell,先安装NuGet包管理器:
Install-PackageProvider NuGet -Force
  1. 安装SNMP解析库SnmpSharpNet:
Install-Package SnmpSharpNet -Scope CurrentUser

(安装后库文件路径大概在C:\Users\<你的用户名>\AppData\Local\NuGet\Packages\SnmpSharpNet\<版本号>\lib\net45\SnmpSharpNet.dll,替换到后续脚本中)

监听脚本

# 加载SNMP解析库,替换为你的实际路径
Add-Type -Path "C:\Users\John\AppData\Local\NuGet\Packages\SnmpSharpNet\0.9.1\lib\net45\SnmpSharpNet.dll"

# 监听UDP 161端口
$udpClient = New-Object System.Net.Sockets.UdpClient(161)
$remoteEP = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Any, 0)

Write-Host "正在监听SNMP Set请求..."

while ($true) {
    # 接收报文
    $receiveBytes = $udpClient.Receive([ref]$remoteEP)
    $snmpPacket = New-Object SnmpSharpNet.SnmpPacket($receiveBytes)

    # 判断是否为Set请求
    if ($snmpPacket.Pdu.Type -eq [SnmpSharpNet.PduType]::Set) {
        Write-Host "收到Set请求,来源IP: $($remoteEP.Address)"
        # 解析请求中的OID和对应值
        foreach ($varBind in $snmpPacket.Pdu.VbList) {
            Write-Host "OID: $($varBind.Oid), 值: $($varBind.Value)"
        }
        # 执行你的目标脚本,替换为实际路径
        & "C:\scripts\your-action-script.bat"
        # 可选:给发送端返回成功响应
        $response = $snmpPacket.Response()
        $udpClient.Send($response.encode(), $response.encode().Length, $remoteEP)
    }
}

注意:必须用管理员权限运行,因为161是特权端口,普通用户无法监听。

Linux平台(Go语言实现)

Go的gosnmp库轻量高效,适合快速搭建监听服务:

前置准备

go get github.com/gosnmp/gosnmp

监听代码

package main

import (
	"fmt"
	"os/exec"

	"github.com/gosnmp/gosnmp"
)

func main() {
	// 配置SNMP参数,替换为你的社区字符串
	params := &gosnmp.GoSNMP{
		Port:      161,
		Community: "public",
		Version:   gosnmp.Version2c,
	}

	// 启动监听,处理Set请求
	err := params.Listen("0.0.0.0", func(packet *gosnmp.SnmpPacket) {
		if packet.PduType == gosnmp.SetRequest {
			fmt.Printf("收到Set请求,来源: %s\n", packet.RemoteAddr)
			// 解析OID和值
			for _, vb := range packet.Variables {
				fmt.Printf("OID: %s, 值: %v\n", vb.Name, vb.Value)
			}
			// 执行目标脚本,替换为实际路径
			cmd := exec.Command("/opt/scripts/your-action.sh")
			if err := cmd.Run(); err != nil {
				fmt.Printf("脚本执行失败: %v\n", err)
			}
			// 返回成功响应
			params.SendResponse(packet, gosnmp.NoError, 0)
		}
	})

	if err != nil {
		fmt.Printf("监听启动失败: %v\n", err)
		return
	}

	select {} // 保持进程运行
}

编译运行:

go build -o snmp-set-trigger .
sudo ./snmp-set-trigger  # 需要sudo监听161端口

零编码快速方案(适合简单场景)

如果不需要解析具体OID,只需要触发脚本,可以用抓包工具配合脚本:

Windows(用WinDump)

  1. 下载WinDump并配置环境变量
  2. 打开命令提示符(管理员),运行:
windump -i any udp port 161 and snmp.set -l | findstr /r "SetRequest" > snmp-set.log
  1. 写个PowerShell脚本实时监控日志文件,发现新内容就执行脚本:
$logFile = "snmp-set.log"
$lastSize = (Get-Item $logFile).Length

while ($true) {
    Start-Sleep -Seconds 1
    $currentSize = (Get-Item $logFile).Length
    if ($currentSize -gt $lastSize) {
        & "C:\scripts\your-action-script.bat"
        $lastSize = $currentSize
    }
}

Linux(用tcpdump)

直接在终端运行:

tcpdump -i any udp port 161 and snmp.set -l | while read -r line; do /opt/scripts/your-action.sh; done

关于Set转Trap的方案(不推荐)

如果非要转Trap,可通过Linux的snmpd配置自定义扩展,当收到Set请求时调用snmp-trap命令发送Trap,但这种方式多了一层中转,效率低且没必要,不如直接捕获解析。


内容的提问来源于stack exchange,提问作者Joel Upham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 22:10:32