10 关于在 proc.mem 和 proc.num 监控项中选择进程的注意事项
修改其命令行参数的进程
某些程序通过修改其命令行作为显示信息的一种方式
他们的当前活动。用户可以通过运行ps查看活动
top 命令。此类程序的示例包括 PostgreSQL
Sendmail, Zabbix.
让我们来看一个来自Linux的示例。假设我们想要监控一个 Zabbix agent进程数量
ps 命令显示相关进程
$ ps -fu zabbix
UID PID PPID C STIME TTY TIME CMD
...
zabbix 6318 1 0 12:01 ? 00:00:00 sbin/zabbix_agentd -c /home/zabbix/ZBXNEXT-1078/zabbix_agentd.conf
zabbix 6319 6318 0 12:01 ? 00:00:01 sbin/zabbix_agentd: collector [idle 1 sec]
zabbix 6320 6318 0 12:01 ? 00:00:00 sbin/zabbix_agentd: listener #1 [waiting for connection]
zabbix 6321 6318 0 12:01 ? 00:00:00 sbin/zabbix_agentd: listener #2 [waiting for connection]
zabbix 6322 6318 0 12:01 ? 00:00:00 sbin/zabbix_agentd: listener #3 [waiting for connection]
zabbix 6323 6318 0 12:01 ? 00:00:00 sbin/zabbix_agentd: active checks #1 [idle 1 sec]
...
按进程名称和用户选择即可完成任务:
$ 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
file 已开启并检查 Name 行。在本例中 Name
行数为:
$ grep Name /proc/{6715,6716,6717,6718,6719,6720}/status
/proc/6715/status:Name: zabbix_agentd_3
/proc/6716/status:Name: zabbix_agentd_3
/proc/6717/status:Name: zabbix_agentd_3
/proc/6718/status:Name: zabbix_agentd_3
/proc/6719/status:Name: zabbix_agentd_3
/proc/6720/status:Name: zabbix_agentd_3
status file 中的进程名称被截断为15个字符。
使用ps命令可以看到类似的结果:
$ ps -u zabbix
PID TTY TIME CMD
...
6715 ? 00:00:00 zabbix_agentd_3
6716 ? 00:00:01 zabbix_agentd_3
6717 ? 00:00:00 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. 未能匹配到来自
status file 当 Zabbix agent 变为 /proc/<pid>/cmdline file。
agent如何查看"cmdline"file可以通过运行一个 命令
$ 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 #1 [waiting for connection]<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会执行
zabbix_agentd_30: collector [idle 1 sec] 来自 cmdline file 和
它不符合我们的name参数zabbix_agentd_30。因此,只有
主进程若未修改其命令行,则会被计入统计。其他
agent进程会修改其命令行参数因而被忽略
此示例表明name参数无法在
proc.mem[] 和 proc.num[] 用于在此情况下选择进程。
使用带有正确正则表达式的cmdline参数可生成
正确结果:
$ zabbix_get -s localhost -k 'proc.num[,zabbix,,zabbix_agentd_30[ :]]'
6
在使用proc.mem[]和proc.num[] 监控项进行监控时需谨慎
修改其命令行参数的程序
在将name和cmdline参数放入proc.mem[]之前
proc.num[] 监控项,您可能需要使用以下参数进行测试
proc.num[] 监控项 和 ps 命令
Linux 内核线程
Threads cannot be selected with cmdline parameter in proc.mem[] and proc.num[] items
以其中一个内核线程为例:
$ ps -ef| grep kthreadd
root 2 0 0 09:33 ? 00:00:00 [kthreadd]
可以通过进程name参数进行选择:
$ 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参数永远无法匹配。
Counting of threads in proc.mem[] and proc.num[] items
Linux内核线程会被proc.num[] 监控项计数,但不会在proc.mem[] 监控项中报告memory。例如:
$ ps -ef | grep kthreadd
root 2 0 0 09:51 ? 00:00:00 [kthreadd]
$ zabbix_get -s localhost -k 'proc.num[kthreadd]'
1
$ zabbix_get -s localhost -k 'proc.mem[kthreadd]'
ZBX_NOTSUPPORTED: Cannot get amount of "VmSize" memory.
但如果存在与内核线程同名的用户进程会怎样?那么情况可能如下:
$ ps -ef | grep kthreadd
root 2 0 0 09:51 ? 00:00:00 [kthreadd]
zabbix 9611 6133 0 17:58 pts/1 00:00:00 ./kthreadd
$ zabbix_get -s localhost -k 'proc.num[kthreadd]'
2
$ zabbix_get -s localhost -k 'proc.mem[kthreadd]'
4157440
proc.num[]会同时统计内核线程和用户进程。proc.mem[]仅报告用户进程的memory,并将内核线程的memory视为0。这与之前报告ZBX_NOTSUPPORTED的情况不同。
当程序名恰好与某个线程匹配时,使用proc.mem[]和proc.num[] 监控项需谨慎。
在将参数放入proc.mem[]和proc.num[] 监控项之前,建议先使用proc.num[] 监控项和ps命令测试参数。