奇怪的ZBX_NOTSUPPORTED问题一则

在监控linux硬件信息的时候,通过system.hw.chassis[serial]监控项来获取设备序列号。本机通过zabbix_agentd命令测试正常

1
2
3
4
[root@localhost ~]# zabbix_agentd -t system.sw.os[name]
system.sw.os[name] [s|Oracle Linux Server 7.8]
[root@localhost ~]# zabbix_agentd -t system.hw.chassis[model]
system.hw.chassis[model] [s|ProLiant DL360 Gen10]

但是在proxy服务器上通过zabbix_get命令获取数据时却发现监控项不支持

1
2
3
4
[root@zabbix-proxy ~]# zabbix_get -s 192.168.2.11 -k system.sw.os[name]
Oracle Linux Server 7.8
[root@zabbix-proxy ~]# zabbix_get -s 192.168.2.11 -k system.hw.chassis[model]
ZBX_NOTSUPPORTED: Cannot obtain hardware information.

至于为什么system.sw.os正常而system.hw.chassis不支持,先来看看二者的解释

  • system.sw.os

    Info is acquired from (note that not all files and options are present in all distributions):
    /proc/version (full)
    /proc/version_signature (short)
    PRETTY_NAME parameter from /etc/os-release on systems supporting it, or /etc/issue.net (name)

  • system.hw.chassis

    This key depends on the availability of the SMBIOS table.
    Will try to read the DMI table from sysfs, if sysfs access fails then try reading directly from memory.

    Root permissions are required because the value is acquired by reading from sysfs or memory.

从这里可以看到如果是要获取system.sw.os的值,则只需要从/proc/version文件或者/proc/version_signature读取信息即可,而这些文件在操作系统上对于所有用户都是可读的。

1
2
[root@localhost ~]# ll /proc/version*
-r--r--r--. 1 root root 0 10月 20 11:14 /proc/version

而当要获取system.hw.chassis值时,是从sysfs里的DMI表去读取,如果sysfs访问失败那么则直接从内存中读取,而这些文件在操作系统上对于zabbix用户都是不可读的。

sysfs 文件系统是一个伪文件系统,它提供内核数据结构的接口。 (更准确地说,sysfs 中的文件和目录提供内核内部定义的 kobject 结构的视图。)sysfs 下的文件提供有关设备、内核模块、文件系统和其他内核组件的信息。

sysfs 文件系统通常安装在/sys目录,默认自动挂载,也可以手动挂载

1
>mount -t sysfs sysfs /sys

/sys/class:
包含终端、网络、设备、块设备、图形设备、声音设备信息等等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[root@localhost id]# cd /sys/class/dmi/id
[root@localhost id]# ll
总用量 0
-r--r--r--. 1 root root 4096 10月 21 11:18 bios_date
-r--r--r--. 1 root root 4096 10月 21 11:18 bios_vendor
-r--r--r--. 1 root root 4096 10月 21 11:18 bios_version
-r--r--r--. 1 root root 4096 10月 21 11:18 board_asset_tag
-r--r--r--. 1 root root 4096 10月 21 11:18 board_name
-r--------. 1 root root 4096 10月 21 11:18 board_serial
-r--r--r--. 1 root root 4096 10月 21 11:18 board_vendor
-r--r--r--. 1 root root 4096 10月 21 11:18 board_version
-r--r--r--. 1 root root 4096 10月 21 11:18 chassis_asset_tag
-r--------. 1 root root 4096 10月 21 11:18 chassis_serial
-r--r--r--. 1 root root 4096 10月 21 11:18 chassis_type
-r--r--r--. 1 root root 4096 10月 21 11:18 chassis_vendor
-r--r--r--. 1 root root 4096 10月 21 11:18 chassis_version
-r--r--r--. 1 root root 4096 10月 21 11:18 modalias
drwxr-xr-x. 2 root root 0 10月 21 11:18 power
-r--r--r--. 1 root root 4096 10月 21 11:18 product_family
-r--r--r--. 1 root root 4096 10月 21 11:18 product_name
-r--------. 1 root root 4096 10月 21 11:18 product_serial
-r--------. 1 root root 4096 10月 21 11:18 product_uuid
-r--r--r--. 1 root root 4096 10月 21 11:18 product_version
lrwxrwxrwx. 1 root root 0 10月 21 11:18 subsystem -> ../../../../class/dmi
-r--r--r--. 1 root root 4096 10月 21 11:18 sys_vendor
-rw-r--r--. 1 root root 4096 10月 21 11:18 uevent

可以直接cat文件读取,但是部分信息的读取需要root权限。内存信息的读取也需要root权限

1
2
[root@localhost id]# ll /dev/mem
crw-r-----. 1 root kmem 1, 1 12月 19 2020 /dev/mem

看到这里很容易联想到是zabbix_agent启动用户的权限问题,默认情况下启动用户为zabbix

1
2
3
4
5
6
7
8
[root@localhost ~]# ps -ef|grep zabbix_agentd
root 20850 20819 0 12:19 pts/2 00:00:00 grep zabbix_agentd
zabbix 61818 1 0 Jul20 ? 00:00:00 /usr/sbin/zabbix_agentd -c /etc/zabbix/zabbix_agentd.conf
zabbix 61819 61818 0 Jul20 ? 01:04:27 /usr/sbin/zabbix_agentd: collector [idle 1 sec]
zabbix 61820 61818 0 Jul20 ? 00:01:47 /usr/sbin/zabbix_agentd: listener #1 [waiting for connection]
zabbix 61822 61818 0 Jul20 ? 00:01:46 /usr/sbin/zabbix_agentd: listener #2 [waiting for connection]
zabbix 61823 61818 0 Jul20 ? 00:01:47 /usr/sbin/zabbix_agentd: listener #3 [waiting for connection]
zabbix 61824 61818 0 Jul20 ? 01:04:11 /usr/sbin/zabbix_agentd: active checks #1 [idle 1 sec]

但是这里又会有一个疑问,因为我的所有客户端配置文件里都是配置了运行root用户运行的,为什么没有生效呢。

1
2
[root@localhost ~]# cat /etc/zabbix/zabbix_agentd.conf |grep AllowRoot
AllowRoot=1

经过查询资料发现,从5.0.0版本开始,官方的zabbix agent包里systemd服务文件更新成明确的指定了服务启动时用到的UserGroup,默认都是设置成了zabbix

这就表示之前旧版本中通过zabbix_agentd.conf指定运行用户的参数被忽略了,从而都以systemd文件里指定的为准。为了覆盖这个新特性,可以通过创建 /etc/systemd/system/zabbix-agent.service.d/override.conf 文件的方式

1
2
3
[Service]
User=root
Group=root

重新加载守护进程和重启zabbix-agent服务:

1
2
systemctl daemon-reload
systemctl restart zabbix-agent

对于Zabbix agent2 来说这种方式完全决定了运行使用的用户。

而对于旧的agent 来说这只是重新让之前的修改zabbix_agentd.conf配置文件的方式生效启用。因此你仍然需要指定 User=rootAllowRoot=1 选项。

在RHEL7中,客户端是通过/usr/lib/systemd/system/zabbix-agent.service服务来管理,则可以通过上面的方式来进行忽略。而在RHEL6环境中则是通过/etc/init.d/zabbix-agent服务来管理,而从4.X升级到5.X时,这个文件也产生了变化。4.X里,启动的命令为daemon $exec -c $conf,而在5.X里变成了daemon $user_conf $exec -c $conf,多了一个$user_conf,这样就导致在启动的时候显式指定了运行的用户为zabbix。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
if [ -f /etc/sysconfig/zabbix-agent ]; then
. /etc/sysconfig/zabbix-agent
fi

if [ -n "$ZABBIX_AGENT_USER" ]; then
user_conf="--user=$ZABBIX_AGENT_USER"
else
user_conf=''
fi

lockfile=/var/lock/subsys/zabbix-agent

start()
{
echo -n $"Starting Zabbix agent: "
daemon $user_conf $exec -c $conf
rv=$?
echo
[ $rv -eq 0 ] && touch $lockfile
return $rv
}

配置文件里定义zabbix-agent启动的用户是由环境变量$ZABBIX_AGENT_USER来决定的,当配置了值时就以配置的用户运行,否则就不显式的指定用户。而这个环境变量则是取的/etc/sysconfig/zabbix-agent里的配置信息。

1
2
3
4
5
[root@localhost ~]# cat /etc/sysconfig/zabbix-agent
# Configuration file for /etc/init.d/zabbix-agent service

# User to run zabbix agent as
ZABBIX_AGENT_USER=zabbix

奇怪的ZBX_NOTSUPPORTED问题一则
https://www.xbdba.com/2021/11/08/zabbix-item-notsupported/
作者
xbdba
发布于
2021年11月8日
许可协议