我们这边有个需求,虽然 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 扯了半小时生成的)
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 就行了。自定义的脚本这样写。自定义监控项的设置自己百度吧,都做监控系统了不要想着一篇文章从开天辟地开始教吧。
#!/bin/bash
lsblk_output=$(lsblk -af --pairs)
echo "$lsblk_output"
然后监控项的话,这样设置,信息类型选文本
预处理的 Javascript 的代码如下,也是我跟 GPT 扯了一小时才可以。跟 GPT 讨论监控项的 js 预处理代码,一定要这样跟 GPT 说好,不然试错几次很烦。(我的 Javascript 环境是基于 Duktape,不支持 let 和 Object.assign 这些函数,需要遍历的地方尽可能用 for。
)
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 需求,哎再说吧。
发表评论