Áú»¢¶Ä²©

10 Remarques sur la s¨¦lection des processus dans les ¨¦l¨¦ments proc.mem et proc.num

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, Áú»¢¶Ä²© sont des exemples de tels programmes.

Voyons un exemple de Linux. Supposons que nous souhaitons surveiller un certain nombre de processus d'agent Áú»¢¶Ä²©.

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 Áú»¢¶Ä²© 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 Áú»¢¶Ä²© 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 Áú»¢¶Ä²© 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.

Threads du noyau Linux

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 Áú»¢¶Ä²© 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.

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.