[comment]: # ({d8848333-75dc9168})
# 10 Remarques sur la sélection des processus dans les éléments proc.mem et proc.num

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

[comment]: # ({77996341-93778d6f})
#### Processus modifiant leur ligne de commande

Certains programmes utilisent la modification de leur ligne de commande
pour afficher leur activité actuelle. Un utilisateur peut voir
l'activité en exécutant les commandes `ps` et `top`. *PostgreSQL*,
*Sendmail*, *Zabbix* sont des exemples de tels programmes.

Voyons un exemple de Linux. Supposons que nous souhaitons surveiller un
certain nombre de processus d'agent Zabbix.

La commande `ps` montre les processus qui nous intéressent

    $ 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]                   
    ...

La sélection des processus par nom et utilisateur fait le travail :

    $ zabbix_get -s localhost -k 'proc.num[zabbix_agentd,zabbix]'
    6

Maintenant, renommons l'exécutable `zabbix_agentd` en `zabbix_agentd_30`
et redémarrons-le.

`ps` montre maintenant

    $ 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]                   
    ...

Maintenant, la sélection des processus par nom et utilisateur produit un
résultat incorrect :

    $ zabbix_get -s localhost -k 'proc.num[zabbix_agentd_30,zabbix]'
    1

Pourquoi un simple changement de nom d'exécutable en un nom plus long
conduit à un résultat assez différent ?

L'agent Zabbix commence par vérifier le nom du processus. Le fichier
`/proc/<pid>/status` est ouvert et la ligne `Name` est cochée. Dans
notre cas, les lignes de `Name` sont :

    $ 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

Le nom du processus dans le fichier `status` est tronqué à 15
caractères.

Un résultat similaire peut être vu avec la commande `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
     ...

Évidemment, `proc.num[]` n'est pas égal à notre valeur de paramètre de
`name` : `zabbix_agentd_30`. N'ayant pas réussi à faire correspondre le
nom de processus du fichier `status`, l'agent Zabbix se tourne vers le
fichier `/proc/<pid>/cmdline`.

La manière dont l'agent voit le fichier "cmdline" peut être illustrée
avec l'exécution d'une commande

    $ 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>...

Les fichiers `/proc/<pid>/cmdline` dans notre cas contiennent des octets
nuls invisibles et non imprimables, utilisés pour terminer les chaînes
en langage *C*. Les octets nuls sont représentés par "<NUL>" dans
cet exemple.

L'agent Zabbix vérifie dans "cmdline" le processus principal et prend
`zabbix_agentd_30`, qui correspond à la valeur du paramètre `name` :
`zabbix_agentd_30`. Ainsi, le processus principal est compté par
l'élément `'proc.num[zabbix_agentd_30,zabbix]`.

Lors de la vérification du processus suivant, l'agent prend
`zabbix_agentd_30: collector [idle 1 sec]` dans le fichier `cmdline` et
il ne correspond pas à notre paramètre `name` `zabbix_agentd_30`. Ainsi,
seul le processus principal qui ne modifie pas sa ligne de commande est
compté. D'autres processus d'agent modifient leur ligne de commande et
sont ignorés.

Cet exemple montre que le paramètre `name` ne peut pas être utilisé dans
`proc.mem[]` et `proc.num[]` pour la sélection de processus dans ce cas.

L'utilisation du paramètre `cmdline` avec une expression régulière
appropriée produit un résultat correct :

    $ zabbix_get -s localhost -k 'proc.num[,zabbix,,zabbix_agentd_30[ :]]'
    6

Soyez prudent lorsque vous utilisez les éléments `proc.mem[]` et
`proc.num[]` pour surveiller les programmes qui modifient leurs lignes
de commande.

Avant de placer les paramètres `name` et `cmdline` dans les éléments
`proc.mem[]` et `proc.num[]`, vous pouvez tester les paramètres à l'aide
de l'élément `proc.num[]` et de la commande `ps`.

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

[comment]: # ({d0ef1ee4-0ff11097})
#### Threads du noyau Linux

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

[comment]: # ({bce5a9fc-3588d8df})
##### Les threads ne peuvent pas être sélectionnés avec le paramètre `cmdline` dans les éléments `proc.mem[]` et `proc.num ]`

Prenons comme exemple l'un des threads du noyau :

    $ ps -ef| grep kthreadd
    root         2     0  0 09:33 ?        00:00:00 [kthreadd]

Il peut être sélectionné avec le paramètre `name` du processus :

    $ zabbix_get -s localhost -k 'proc.num[kthreadd,root]'
    1

Mais avec la sélection par processus, le paramètre cmdline ne fonctionne
pas :

    $ zabbix_get -s localhost -k 'proc.num[,root,,kthreadd]'
    0

La raison en est que l'agent Zabbix prend l'expression régulière
spécifiée dans le paramètre `cmdline` et l'applique au contenu du
processus `/proc/<pid>/cmdline`. Pour les threads du noyau, leurs
fichiers `/proc/<pid>/cmdline` sont vides. Ainsi, le paramètre `cmdline`
ne correspond jamais.

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

[comment]: # ({b63fbbf2-8d1ef0a6})
##### Comptage des threads dans les éléments `proc.mem[]` et `proc.num[]`

Les threads du noyau Linux sont comptés par l'élément `proc.num[]` mais
ne signalent pas la mémoire dans l'élément `proc.mem[]`. Par exemple :

    $ 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.

Mais que se passe-t-il si un processus utilisateur porte le même nom
qu'un thread du noyau ? Alors cela pourrait ressembler à ceci :

    $ 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[]` compte à la fois le thread du noyau et le processus
utilisateur. `proc.mem[]` rapporte la mémoire pour le processus
utilisateur uniquement et compte la mémoire du thread du noyau comme si
elle était à 0. Cela est différent du cas ci-dessus lorsque
ZBX\_NOTSUPPORTED a été signalé.

Soyez prudent lorsque vous utilisez les éléments `proc.mem[]` et
`proc.num[]` si le nom du programme correspond à l'un des threads.

Avant de mettre des paramètres dans les éléments `proc.mem[]` et
`proc.num[]`, vous pouvez les tester à l'aide de l'élément `proc.num[]`
et de la commande `ps`.

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