Finer04's Blog
首页
乱写一通
脑洞破文
随便谈谈
当前播放.page
Zabbix 获取 Linux 系统的所有分区的 UUID
Finer04
February 3, 2024
4107 字
文章目录
我们这边有个需求,虽然 Zabbix-Agent 可以获取所有分区的空间利用率的监控项,但是我们需要将服务器的所有数据对接到上游的监管系统,监管平台的厂商说为了确保唯一性,我们提供给他们的数据一定要有所有分区的 UUID。这可把我整蒙了,他们不能自己生成一个 UUID 嘛?这个需求也是冷门需求反正我谷歌也没类似的案例,只能靠自己了。 ## 不使用自定义监控项的方法 经过我占用了 3 小时工时的研究下,在不做自定义监控项且不运行系统命令 (system.run 监控项是默认关闭也不可能开启的) 的情况下,只能读取 `/etc/fstab` 分区的 UUID 和挂载位置了。 我曾经想利用 `vfs.dir.get["/dev/disk/by-uuid/"]` 获取这个目录的数据,因为可以输出磁盘的 UUID 和软链接的最终位置,但是在 Zabbix 输出的结果是只有 UUID,软链接的路径不会输出,不符合我的需求。如果要输出的话还是得自定义监控项。  但是 `/etc/fstab` 看 UUID 和挂载位置有个问题,就是挂载的磁盘不一定只能用 UUID 挂载,只是 UUID 的唯一性好很多,有时候用 LVM 的路径挂载也可以挂载到。所以说这个方法只适用于有规范性操作指引且用户不用 LVM 卷只能标准分区。因为我只要输出 json 就行了,如果要用 LLD 自动发现的话,记得用 `相关项目` 关联监控项哦。 - 键值: vfs.file.contents["/etc/fstab"] - 预处理选 Javascript,代码这样写(代码我是跟 GPT 扯了半小时生成的) ```javascript const fstabContent = value; // 正则表达式用于匹配 UUID 和分区信息 const uuidPattern = /UUID=("|')?([^"'\s]+)\1\s+(\S+)\s+/g; // 匹配所有符合条件的结果 var matches = []; var match; while ((match = uuidPattern.exec(fstabContent)) !== null) { matches.push({ UUID: match[2], Partition: match[3] }); } return JSON.stringify(matches, null, 0); ```  ### 测试结果 测试是成功的,正则对用了双引号或单引号整了点容错性。  如果主机的分区都是 LVM 的话,那就歇菜了。不适用这个方法了。  ## 使用自定义监控项 所以说,这也太将就了,到时候万一都用 LVM 卷了我这个岂不是完了。自定义监控项玩法就多了。系统还可以看分区的 UUID 的命令还有 `blkid` 和 `lsblk`,我看了下还是选择 lsblk 作为自定义监控项吧。但是有个问题,我用麒麟和统信和 CentOS,输出结果字段是不同的。查看就是不同的内核版本的 util-linux 组件的版本也不同(不对啊,我阿里的是5.10,util组件是2.32;麒麟的是 4.19,组件是 2.35)。`lsblk` 使用 `--pairs` 可以以 `key-value` 的形式输出,新版可以用 json 输出,但是大家也知道什么叫 `新版`。新版的好处还可以输出空间占用率。  我们先不管这个问题,反正有 UUID 就行了。自定义的脚本这样写。自定义监控项的设置自己百度吧,都做监控系统了不要想着一篇文章从开天辟地开始教吧。 ```bash #!/bin/bash lsblk_output=$(lsblk -af --pairs) echo "$lsblk_output" ``` 然后监控项的话,这样设置,信息类型选文本  预处理的 Javascript 的代码如下,也是我跟 GPT 扯了一小时才可以。跟 GPT 讨论监控项的 js 预处理代码,一定要这样跟 GPT 说好,不然试错几次很烦。(`我的 Javascript 环境是基于 Duktape,不支持 let 和 Object.assign 这些函数,需要遍历的地方尽可能用 for。`) ```javascript const lines = value.trim().split('\n'); var formattedOutput = {}; for (var i = 0; i < lines.length; i++) { var parts = lines[i].split(' '); // Ensure the line has at least 5 parts before attempting to access them if (parts.length >= 5) { var deviceName = parts[0].replace('NAME="', '').replace('"', ''); var fstype = parts[1].replace('FSTYPE="', '').replace('"', ''); var fsver = ''; var label = ''; var uuid = ''; var fsavail = ''; var fsusePercent = ''; var mountpoint = ''; for (var j = 2; j < parts.length; j++) { var keyValue = parts[j].split('='); var key = keyValue[0]; var value = keyValue[1] ? keyValue[1].replace(/"/g, '') : ''; switch (key) { case 'FSVER': fsver = value; break; case 'LABEL': label = value; break; case 'UUID': uuid = value; break; case 'FSAVAIL': fsavail = value; break; case 'FSUSE%': fsusePercent = value; break; case 'MOUNTPOINT': mountpoint = value; break; } } // Manually merge attributes without using Object.assign var mergedAttributes = { fstype: fstype, fsver: fsver, label: label, uuid: uuid, fsavail: fsavail, fsusePercent: fsusePercent, mountpoint: mountpoint, }; formattedOutput[deviceName] = mergedAttributes; } } // Convert formatted output to JSON var jsonOutput = JSON.stringify(formattedOutput, null, 0); return jsonOutput; ``` 上面的代码也是有容错性,兼容我上面截图的两种输出情况。输出结果如下,如果 lsblk 是旧版的话,只是很多字段都空出来了,该有的值都有的。  如果后面还有需求看 VG 卷或 LV 卷的 UUID 需求,哎再说吧。
评论已关闭
▲ Top
评论已关闭