9 在proc.mem和proc.num项目中选择进程的注意事项
修改其命令行的进程
让我们来看一个Linux的例子,假设我们想要监视许多Zabbix agent进程。
ps
命令显示的进程如下
通过名称和用户选择进程来完成任务:
$ zabbix_get -s localhost -k 'proc.num[zabbix_agentd,zabbix]'
6
现在让我们将 zabbix_agentd
重命名为 zabbix_agentd_30
并重新启动它。
ps
现在显示为
$ ps -fu zabbix
UID PID PPID C STIME TTY TIME CMD
...
zabbix 6715 1 0 12:53 ? 00:00:00 sbin/zabbix_agentd_30 -c /home/zabbix/ZBXNEXT-1078/zabbix_agentd.conf
zabbix 6716 6715 0 12:53 ? 00:00:00 sbin/zabbix_agentd_30: collector [idle 1 sec]
zabbix 6717 6715 0 12:53 ? 00:00:00 sbin/zabbix_agentd_30: listener #1 [waiting for connection]
zabbix 6718 6715 0 12:53 ? 00:00:00 sbin/zabbix_agentd_30: listener #2 [waiting for connection]
zabbix 6719 6715 0 12:53 ? 00:00:00 sbin/zabbix_agentd_30: listener #3 [waiting for connection]
zabbix 6720 6715 0 12:53 ? 00:00:00 sbin/zabbix_agentd_30: active checks #1 [idle 1 sec]
现在根据名称和用户选择进程会产生不正确的结果:
$ zabbix_get -s localhost -k 'proc.num[zabbix_agentd_30,zabbix]'
1
为什么将可执行文件重命名为更长的名称会导致完全不同的结果?
Zabbix agent 启动时检查进程名字, /proc/<pid>/status
文件是打开的并且检查 Name
行。 我们的例子中 Name
行如下:
ps
命令会产生相似的结果:
$ ps -u zabbix
PID TTY TIME CMD
...
6715 ? 00:00:00 zabbix_agentd_3
6716 ? 00:00:01 zabbix_agentd_3
6718 ? 00:00:00 zabbix_agentd_3
6719 ? 00:00:00 zabbix_agentd_3
6720 ? 00:00:00 zabbix_agentd_3
...
显然, 跟我们的 proc.num[]
name
参数值 zabbix_agentd_30
并不一样。 Zabbix agent从status
文件中匹配进程名失败后,会转到 /proc/<pid>/cmdline
文件。
agent如何看待“cmdline”文件,可以通过运行一个命令来说明
$ for i in 6715 6716 6717 6718 6719 6720; do cat /proc/$i/cmdline | awk '{gsub(/\x0/,"<NUL>"); print};'; done
sbin/zabbix_agentd_30<NUL>-c<NUL>/home/zabbix/ZBXNEXT-1078/zabbix_agentd.conf<NUL>
sbin/zabbix_agentd_30: collector [idle 1 sec]<NUL><NUL><NUL><NUL><NUL><NUL><NUL><NUL><NUL><NUL><NUL><NUL><NUL>...
sbin/zabbix_agentd_30: listener #2 [waiting for connection]<NUL><NUL><NUL><NUL><NUL><NUL><NUL><NUL><NUL><NUL>...
sbin/zabbix_agentd_30: listener #3 [waiting for connection]<NUL><NUL><NUL><NUL><NUL><NUL><NUL><NUL><NUL><NUL>...
sbin/zabbix_agentd_30: active checks #1 [idle 1 sec]<NUL><NUL><NUL><NUL><NUL><NUL><NUL><NUL><NUL><NUL><NUL><NUL>...
/proc/<pid>/cmdline
文件包含在 C 语言中用于终止字符的隐藏的、 不可显示的空字符 。 这个例子中空字符以 “<NUL>” 形式出现。
Zabbix agent 检查 “cmdline” ,得到 zabbix_agentd_30
值, 该值匹配我们的name
参数值 zabbix_agentd_30
。 因此, 主进程会被监控项 proc.num[zabbix_agentd_30,zabbix]
计数。
当检查下一进程时, agent 从cmdline
文件中得到 zabbix_agentd_30: collector [idle 1 sec]
,但不匹配 name
参数值 zabbix_agentd_30
。 所以,只有不改变命令行的主进程被计数, 其他的 agent 进程改变了命令行而被忽略。
这个例子展示了 name
参数不能用在 proc.mem[]
和 proc.num[]
监控项中来选择进程。
cmdline
参数使用恰当的正则表达式会达到一个正确的结果:
$ zabbix_get -s localhost -k 'proc.num[,zabbix,,zabbix_agentd_30[ :]]'
6
在将 name
和 cmdline
参数放入 proc.mem[]
和 项之前,您可能需要使用 proc.num[]
项和 ps
命令测试参数.
Linux 内核线程
proc.mem[]
和 proc.num[]
监控项中的 cmdline
参数不可以使用线程
让我们以内核线程为例:
可以用进程 名称
参数选择:
$ zabbix_get -s localhost -k 'proc.num[kthreadd,root]'
1
但使用进程cmdline
参数就不起作用:
$ zabbix_get -s localhost -k 'proc.num[,root,,kthreadd]'
0
原因是Zabbix agent采用“cmdline”参数中指定的正则表达式,并将其应用于进程的内容 /proc/<pid>/cmdline
. 对于内核线程的 /proc/<pid>/cmdline
文件是空的, 所以, cmdline
参数不会匹配到。
proc.mem[]
和proc.num[]
监控项中的线程计数
Linux 内核线程通过proc.num[]
监控项计数,但是 proc.mem[]
监控项并不报告内存。 例如:
$ ps -ef | grep kthreadd
root 2 0 0 09:51 ? 00:00:00 [kthreadd]
$ zabbix_get -s localhost -k 'proc.num[kthreadd]'
1
ZBX_NOTSUPPORTED: Cannot get amount of "VmSize" memory.
但是如果用户线程和内核线程名字相同会发生什么呢 ? 可能会是这样:
proc.num[]
计算内核线程和用户进程。 proc.mem[]
只计算用户进程内存,如果为0计算内核线程内存。这和上面报告 ZBX_NOTSUPPORTED 的例子不同。
在给 proc.mem[]
和proc.num[]
监控项配置参数时, 你应该使用 proc.num[]
监控项 和 ps
命令测试该参数。