☰
基于SNMP的打印机实时监控方案:原理与Python实现
2026/10/2 19:37:42 网站建设 项目流程

简介:面向IT运维与企业办公管理者的实时监控打印机状态资料包,系统梳理从设备运行状态采集到打印报表分析的关键知识点,可帮助读者理解如何利用SNMP、WMI及现有监控软件跟踪打印队列、耗材余量、作业时间与文档日志,并规划故障预警和资源优化策略。资源包共106个文件,主体为JSON数据文件和HTML页面,另有少量ZIP压缩包,整体仅2.25MB,便于下载后快速浏览和复用。内容兼顾技术原理与落地实践,涵盖打印状态监测、时间追踪、份数统计、敏感信息保护等议题,并点出故障预警、资源优化和报表分析的常见工具思路,适合正在搭建打印监控体系或希望通过轻量手段提升打印效率的管理者参考。目前已有2281人学习下载,适合IT运维、行政办公及教学演示等场景作为实用参考。 搞IT最怕的就是办公室突然冒出来一句“打印机坏了”,等你跑到现场一看,十次里有七次是没纸了、卡纸了、机器离线路由器没给它好脸。真正主板烧了、定影组件挂掉的情况反而少见。

以前我管办公室设备的时候,基本都是靠行政同事跑来报修,再去检查。后来发现这办法太被动,员工一打印就发现缺墨、离线,工作效率全耽误在这台小机器上。于是我开始琢磨怎么把“实时监控打印机状态”这件事做成一套固定系统,让设备状态自己会说话,该告警告警,该预警预警。这篇文章就把我从需求拆解、协议选型到脚本实现、落地排障的整个过程整理出来,给你一个可以直接参考复现的方案,尤其适合中小企业IT、行政和运维同学。

1. 为什么要做打印机实时监控:需求拆解与方案选型

1.1 打印机状态里藏着哪些关键信息

很多人以为监控打印机就是看在线还是离线,真做起来你会发现,可监控的信息比想象的要多得多,也实用得多。

  • 在线/离线状态:设备是否可达,网络是否正常。
  • 运行状态码:设备是否报错,处于空闲、打印中、卡纸、开门报错等状态。
  • 耗材余量:墨粉、墨盒、硒鼓、废粉仓的剩余百分比。
  • 纸张与纸盒状态:哪个纸盒缺纸、有没有卡纸。
  • 打印页数计数:总打印页数,可用于成本核算和设备维护周期判断。
  • 固件/型号信息:设备型号、序列号、固件版本,方便做资产台账。

这些信息组合起来能解决很多实际管理问题:耗材不用等用户喊“没墨了”再买,设备故障可以在上班前发现,打印量还能按部门统计出来做成本分摊。可以说,一套状态监控系统不只是“看设备是否活着”,而是一套设备健康度管理工具。

1.2 商业平台、开源监控、自研脚本怎么选

明确了要看哪些指标,下一个问题是:用什么方式实现?我当时在三个方向之间犹豫过,对应三种典型思路,这里列个对比:

方案方向代表产品/技术优点缺点适合场景
商业打印管理平台PaperCut、Printix、惠普智系列管理平台等功能全,自带计费、权限、报表,部署后很省心按设备或按用户收费,小规模环境下成本高中大型企业,打印量高、有计费需求的场景
通用监控平台扩展Zabbix、Cacti、LibreNMS + SNMP模板一套系统能顺便把网络设备、服务器一起监控,生态成熟打印机专属维度少,耗材、页数采集需要自己调模板已经有监控系统,想直接纳管打印机的环境
自研轮询脚本Python + SNMP 工具灵活可控,想采集什么就采集什么,部署轻量需要自己维护,功能相对简单打印机数量在几台到几十台,预算有限的中小环境

我最后选了自研脚本。原因很直接:公司打印机几十台,商用平台的费用比一年粉墨开支还高,Zabbix虽然免费但为了几十台打印机单独维护一套监控体系有点杀鸡用牛刀,而用Python写一个实时轮询脚本,半小时就能跑通,成本几乎为零,后续按需加指标也很方便。如果打印机规模上百台,那我会认真劝你直接用成熟平台,采集、告警、报表都省心。

2. 监控核心原理:SNMP协议与打印机MIB

2.1 SNMP协议基础与为什么打印机都支持

自研方案里,最关键的选型就是采用SNMP(简单网络管理协议)来采集打印机状态。为什么是SNMP,而不是写个软件装在电脑上、或者解析打印机网页管理界面?原因有四条:

  • 原生支持,不需要装客户端:绝大多数支持网络打印的设备和打印机,固件里自带SNMP Agent,直接在网管界面打开开关就能用,不需要在设备上装任何东西。
  • 跨品牌兼容性好:惠普、佳能、爱普生、兄弟、富士施乐等主流厂商都实现了标准SNMP MIB,尤其是Printer-MIB(标准编号 1.3.6.1.2.1.43),很多基础状态字段一致。
  • 轻量高效:SNMP走UDP 161端口,单个请求也就几百字节,对打印机本身性能影响很小。
  • 生态成熟:Linux下net-snmp工具链齐全,写脚本、调试非常方便。

原理上,SNMP就是“管理端”向“被管设备”发一种类似“字典查询”的请求:每个被监控的参数都对应一个唯一的对象标识符,也就是OID。管理端发请求去取某个OID对应的值,设备返回字符串或数字。把OID理解成设备内部参数的“门牌号”就行。

2.2 高频使用的OID参考与字段含义

我用到的OID不算多,但都是高频且相对通用的,整理成下面的表方便你直接抄:

用途OID返回值示例说明
设备描述1.3.6.1.2.1.1.1.0STRING: HP LaserJet M428-M429设备型号、固件信息
设备名称1.3.6.1.2.1.1.5.0STRING: 前台打印机打印机自定义名称
运行状态1.3.6.1.2.1.25.3.2.1.5.1INTEGER: 11正常、2警告、3故障(需实测确认)
耗材余量(标准MIB)1.3.6.1.2.1.43.11.1.1.9INTEGER: 80通常为百分比,多个耗材时带不同索引
总打印页数1.3.6.1.2.1.43.10.2.1.4.1.1Counter32: 15234累计打印计数
当前任务状态1.3.6.1.2.1.43.5.1.1.5.1INTEGER: 3打印任务状态(空闲/打印中/暂停)

注意一个坑:耗材余量OID在标准Printer-MIB里定义得很好,但不同厂商实现差异很大。有的机器黑色、彩色、废粉仓分别占不同的表索引,有的直接用私有OID。所以实际调试时,不要只盯着1.3.6.1.2.1.43.11.1.1.9这一个节点,而是应该用snmpwalk把整棵子树拉出来看一遍,找到真正对应的字段。后面我会详细演示。

另外,运行状态码1、2、3这种映射不是所有机器都一致,尤其是“2”到底是缺纸还是警告,不同厂商可能有差异。稳妥做法是实测:先读取空闲状态的返回值,再人为拔掉纸盒/打开盖子,观察状态码怎么变,用两次对比结果来确定告警阈值。

3. 从零搭建一套可用的实时监控脚本

3.1 环境准备与先用命令行验证

我用来跑监控的是一台Linux服务器,其实拿树莓派或者一台不关机的旧电脑也一样。以Debian/Ubuntu为例,先安装net-snmp工具包:

sudo apt update sudo apt install -y snmp snmpwalk snmpget python3 python3-pip

先别急着写代码,用命令行验证一下打印机SNMP通不通,这能省下大量调试时间。查设备描述和耗材余量:

snmpget -v2c -c public 192.168.1.100 1.3.6.1.2.1.1.1.0 snmpwalk -v2c -c public 192.168.1.100 1.3.6.1.2.1.43.11.1.1.9

第一个命令看设备基本信息,第二个命令会列出所有耗材节点。如果返回结果正常,说明设备SNMP已经开着了;如果提示Timeout,在打印机网管界面里确认SNMP是否开启、community(团体名,默认一般是public)是否匹配,同时检查服务器的防火墙是否放行UDP 161。

3.2 写一个多打印机轮询脚本

命令行验证通过后,写正式脚本。我在Python里没有用额外的SNMP库,而是直接调snmpget命令行工具,好处是少一层依赖问题,输出解析也直观,方便排障。脚本核心代码如下:

#!/usr/bin/env python3 import subprocess import time import requests from datetime import datetime # 打印机清单,按实际情况修改 IP、community PRINTERS = [ {"name": "前台打印机", "ip": "192.168.1.100", "community": "public"}, {"name": "财务室打印机", "ip": "192.168.1.101", "community": "public"}, {"name": "设计部彩色机", "ip": "192.168.1.102", "community": "public"}, ] # 要采集的标准 OID OIDS = { "device_desc": "1.3.6.1.2.1.1.1.0", "device_name": "1.3.6.1.2.1.1.5.0", "run_status": "1.3.6.1.2.1.25.3.2.1.5.1", "toner_level": "1.3.6.1.2.1.43.11.1.1.9.1.1", "total_page": "1.3.6.1.2.1.43.10.2.1.4.1.1", } def snmp_get(ip, community, oid): """执行 snmpget 并返回等号后面的值""" try: out = subprocess.check_output( ["snmpget", "-v2c", "-c", community, "-t", "3", "-r", "1", ip, oid], stderr=subprocess.STDOUT, text=True, timeout=10, ) # 输出形如 "OID = INTEGER: 80",取等号后的内容 if "=" in out: return out.split("=", 1)[1].strip() return f"UNKNOWN: {out.strip()}" except subprocess.CalledProcessError as e: return f"ERROR: {e.output.strip()}" except Exception as e: return f"ERROR: {str(e)}" def send_dingtalk(content): """把告警消息推到钉钉机器人,按需替换 webhook 地址和方法""" webhook = "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN" try: requests.post(webhook, json={ "msgtype": "text", "text": {"content": content} }, timeout=5) except Exception as e: print(f"[告警推送失败] {e}") def check_one_printer(p): status = snmp_get(p["ip"], p["community"], OIDS["run_status"]) toner = snmp_get(p["ip"], p["community"], OIDS["toner_level"]) now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") print(f"[{now}] {p['name']} ({p['ip']}) 状态={status} 耗材={toner}") # 状态码或关键字包含 ERROR,说明设备不可达 if "ERROR" in status or "ERROR" in toner: send_dingtalk(f"⚠️ {p['name']} 可能离线或 SNMP 异常:{status} / {toner}") # 耗材数值小于 15,触发预警 elif toner.isdigit() and int(toner) < 15: send_dingtalk(f"⚠️ {p['name']} 耗材剩余 {toner}%,请准备更换耗材") def main(): while True: for p in PRINTERS: check_one_printer(p) time.sleep(60) if __name__ == "__main__": main()

代码逻辑不复杂:主循环每分钟遍历所有打印机,读取运行状态和耗材余量;设备不可达或耗材低于阈值时,通过钉钉机器人推消息。打印部分会输出到控制台,方便你观察日志。如果你不想用钉钉,把send_dingtalk函数里的requests.post换成SMTP邮件发送,改造思路类似。

这里要提醒一句:上面的耗材OID我写的是1.3.6.1.2.1.43.11.1.1.9.1.1,但实际打印机上耗材索引很可能不是唯一的,黑色墨粉、彩色墨粉、废粉仓对应不同的最后一段数字。你拿到机器后,先用snmpwalk输出真正的索引,再把OID改成实际值,不要直接抄默认配置。

3.3 把状态变成可视化看板与数据归档

轮询脚本只是第一步,人不可能一直盯控制台。我后续做了两件事:数据归档和可视化。

数据归档很简单,脚本里把每次采集结果追加到SQLite或CSV里。比如用一个printer_status.csv,字段包括时间戳、打印机名、IP、运行状态、耗材余量、总页数,这个文件直接就能用Excel打开,月末还能拿来做打印量统计。

可视化要省事的话,最不需要造轮子的方案是把数据接进Grafana。社区里有现成的打印机状态看板模板,只要数据源能查到SQLite、MySQL或者InfluxDB,配置几分钟就能出来一个大屏,在线状态、耗材趋势、打印量排行都能看。如果只想临时看个页面,也可以用FastAPI或Flask写个只读接口,把CSV文件里的最新状态读出来渲染成HTML,够用就行。

3.4 监控频率怎么定:轮询策略与资源平衡

有一个参数很容易被忽略,但实际很重要——轮询频率。我见过有人为了“实时”把轮询间隔设成10秒,结果打印机控制板CPU占满,打印速度肉眼可见变慢,这属于把监控做成了事故源。

  • 在线状态、运行状态:建议60秒轮询一次,足够满足实时感。
  • 耗材余量、打印页数:变化缓慢,5分钟一次就够,没人需要秒级知道墨粉从80%变79.9%。
  • 告警推送:建议做去重,比如耗材低于15%只在首次触发时推一次,否则每60秒推一遍,钉钉群会炸。

4. 落地部署中的常见问题与排查技巧

4.1 高频坑位速查表

实际部署阶段我遇到的坑,几乎全都能归纳成下面这几类。整理成速查表,你对照着处理就行:

现象可能原因排查与解决
snmpget超时无响应打印机SNMP未启用登录打印机Web管理页,找到“网络/SNMP”选项,启用SNMP v1/v2c并确认团体名
机器明明在打印,但脚本报离线服务器防火墙拦截UDP 161出站,或打印机ACL限制了来源IP检查服务器防火墙,给打印机IP配置SNMP访问白名单,允许服务器IP访问
返回noSuchNameOID在该机型上不存在用snmpwalk扫描1.3.6.1.2.1.43整棵子树,找到厂商实际的OID节点
耗材值拿不到百分比私有MIB未按标准实现优先用snmpwalk看返回值;部分机型返回值可能是页数、克数等,需要自己换算百分比
状态码含义和文档不一致厂商对INTEGER值的映射有差异人为制造故障(拔纸、开门、卡纸)对比状态码变化,建立自己的映射表
监控脚本跑了几天突然挂掉日志文件越来越大,或Python进程被OOM杀掉用systemd服务管理脚本,设置Restart=always,开启logrotate切割日志
打印机IP变了导致监控失效设备通过DHCP动态获取IP给打印机在路由器里设置DHCP保留,或改为静态IP并绑定MAC

这里单独展开一下“用snmpwalk找私有OID”的方法,这是最常用的排障手段。以找耗材OID为例:

snmpwalk -v2c -c public 192.168.1.100 1.3.6.1.2.1.43.11.1.1.9

输出里你会看到类似:

SNMPv2-SMI::mib-2.43.11.1.1.9.1.1 = INTEGER: 80 SNMPv2-SMI::mib-2.43.11.1.1.9.1.2 = INTEGER: 60

两个索引值通常对应不同耗材仓。这时候逐个去测:把黑墨粉取出来或者故意用低墨盒打印,看哪个索引的值下降,就知道哪个是黑粉仓、哪个是彩色粉仓。这个方法比翻几百页技术文档快得多。

4.2 现场部署的几点实战经验

最后说几条我在实际部署中非常管用的经验,属于那种“文档里不会写、用起来真能救命”的细节。

第一,上线之前把打印机的SNMP community从默认的public改掉。虽然内部网络相对安全,但公共团体名意味着同一局域网任何人都能通过snmpwalk摸清你的打印量、耗材余量,一些攻击者可以利用这些信息判断设备型号和漏洞。改成不容易猜的团体名,成本几乎为零。

第二,告警一定要设置“静默窗口”。凌晨三点的打印机关机告警没有任何意义,只会把值班手机打爆。我在脚本里直接处理了这个逻辑:非工作时间只记录、不发送告警,工作时间才真正推送。实现不复杂,用datetime判断当前时间落在哪个时间段就行。

第三,状态监控上线后,建议先跑一个星期“只记录、不告警”。让脚本先把所有打印机的真实数据采一遍,你会对设备状况有完全不同的认知——哪台机器每天掉线三次、哪台墨粉余量一直报警但实际还能打五百页、哪台总页数增长异常需要关注。摸清了这个底,再逐步打开告警规则,才不会第一天就被误报淹没。

这套系统我实际跑了将近一年,最大的感受是:IT值班电话少了一大半,行政批量采购耗材的时候也有了数据支撑。打印机这种设备,看起来默默无闻,但其实很适合用SNMP这套传统协议管理起来。你要做的只是把它加入监控名单,剩下的交给脚本就行。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询