[comment]: # translation:outdated

[comment]: # ({75dc9168-75dc9168})
# 10 关于在 proc.mem 和 proc.num 监控项中选择进程的注意事项

[comment]: # ({/75dc9168-75dc9168})

[comment]: # ({93778d6f-93778d6f})
#### 修改其命令行参数的进程

某些程序通过修改其命令行作为显示信息的一种方式
他们的当前活动。用户可以通过运行`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` 命令

[comment]: # ({/93778d6f-93778d6f})

[comment]: # ({0ff11097-0ff11097})
#### Linux 内核线程

[comment]: # ({/0ff11097-0ff11097})

[comment]: # ({3588d8df-3588d8df})
##### 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`参数永远无法匹配。

[comment]: # ({/3588d8df-3588d8df})

[comment]: # ({8d1ef0a6-8d1ef0a6})
##### 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`命令测试参数。

[comment]: # ({/8d1ef0a6-8d1ef0a6})
