9 Notities over het selecteren van processen in proc.mem- en proc.num-items

Processen die hun opdrachtregel wijzigen

Sommige programma's gebruiken het wijzigen van hun opdrachtregel als een methode om hun huidige activiteit weer te geven. Een gebruiker kan de activiteit zien door de commando's ps en top uit te voeren. Voorbeelden van dergelijke programma's zijn PostgreSQL, Sendmail en Zabbix.

Laten we een voorbeeld bekijken vanuit Linux. Laten we aannemen dat we een aantal Zabbix-agentprocessen willen monitoren.

Het ps-commando toont de relevante processen als volgt:

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

Het selecteren van processen op naam en gebruiker werkt:

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

Laten we nu de uitvoerbare naam zabbix_agentd hernoemen naar zabbix_agentd_30 en deze opnieuw starten.

ps toont nu:

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

Nu levert het selecteren van processen op naam en gebruiker een onjuist resultaat op:

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

Waarom leidde een eenvoudige hernoeming van de uitvoerbare naam naar een langere naam tot een heel ander resultaat?

De Zabbix-agent begint met het controleren van de procesnaam. Het bestand /proc/<pid>/status wordt geopend en de regel Name wordt gecontroleerd. In ons geval zijn de Name-regels:

$ 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

De procesnaam in het status-bestand is afgekapt tot 15 tekens.

Een vergelijkbaar resultaat kan worden gezien met het ps-commando:

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

Duidelijk is dat dit niet gelijk is aan onze proc.num[] name-parameterwaarde zabbix_agentd_30. Omdat de Zabbix-agent de procesnaam in het status-bestand niet kon vinden, kijkt hij naar het bestand /proc/<pid>/cmdline.

Hoe de agent het "cmdline"-bestand ziet, kan worden geïllustreerd door een commando uit te voeren:

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

De /proc/<pid>/cmdline-bestanden bevatten in ons geval onzichtbare, niet-afdrukbare nulbytes die worden gebruikt om strings in de C-taal te beëindigen. De nulbytes worden in dit voorbeeld weergegeven als "<NUL>".

De Zabbix-agent controleert "cmdline" voor het hoofdproces en neemt een zabbix_agentd_30, die overeenkomt met onze name-parameterwaarde zabbix_agentd_30. Dus, het hoofdproces wordt geteld door het item proc.num[zabbix_agentd_30,zabbix].

Bij het controleren van het volgende proces neemt de agent zabbix_agentd_30: collector [idle 1 sec] uit het cmdline-bestand en dit komt niet overeen met onze name-parameter zabbix_agentd_30. Daarom wordt alleen het hoofdproces dat zijn opdrachtregel niet wijzigt, geteld. Andere agentprocessen wijzigen hun opdrachtregel en worden genegeerd.

Dit voorbeeld laat zien dat de name-parameter niet kan worden gebruikt in proc.mem[] en proc.num[] om processen in dit geval te selecteren.

Voor het proc.get[]-item zal de Zabbix-agent bij het controleren van "cmdline" voor de procesnaam alleen een deel van de naam gebruiken dat begint vanaf de laatste schuine streep en tot aan het eerste spatie- of kolontecken. De procesnaam die is ontvangen uit het cmdline-bestand wordt alleen gebruikt als het begin volledig overeenkomt met de verkorte procesnaam in het status-bestand. Het algoritme is hetzelfde voor zowel de procesnaam in het filter als in de JSON-uitvoer.

Het gebruik van de cmdline-parameter met een juiste reguliere expressie levert een correct resultaat op:

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

Wees voorzichtig bij het gebruik van proc.get[], proc.mem[] en proc.num[]-items voor het monitoren van programma's die hun opdrachtregels wijzigen.

Voordat je de name- en cmdline-parameters in proc.get[], proc.mem[] en proc.num[]-items plaatst, wil je wellicht de parameters testen met behulp van het proc.num[]-item en het ps-commando.

Linux-kernelthreads

Threads kunnen niet worden geselecteerd met de cmdline-parameter in proc.get[], proc.mem[] en proc.num[]-items

Laten we als voorbeeld een van de kernelthreads nemen:

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

Het kan worden geselecteerd met de proces name-parameter:

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

Maar selectie op basis van de proces cmdline-parameter werkt niet:

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

De reden hiervoor is dat de Zabbix-agent de reguliere expressie neemt die is opgegeven in de cmdline-parameter en deze toepast op de inhoud van het proces /proc/<pid>/cmdline. Voor kernelthreads zijn hun /proc/<pid>/cmdline-bestanden leeg. Dus, de cmdline-parameter komt nooit overeen.

Tellen van threads in proc.mem[] en proc.num[] items

Linux-kernelthreads worden geteld door het item proc.num[] maar rapporteren niet geheugen in proc.mem[] item. Bijvoorbeeld:

$ ps -ef | grep kthreadd
       wortel 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: Kan de hoeveelheid "VmSize"-geheugen niet ophalen.

Maar wat gebeurt er als er een gebruikersproces is met dezelfde naam als a kern draad? Dan zou het er zo uit kunnen zien:

$ ps -ef | grep kthreadd
       wortel 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[] telde zowel de kernelthread als het gebruikersproces. proc.mem[] rapporteert alleen geheugen voor het gebruikersproces en telt de kernelthread-geheugen alsof het 0 is. Dit is anders dan het geval hierboven wanneer ZBX_NOTSUPPORTED werd gerapporteerd.

Wees voorzichtig bij het gebruik van proc.mem[] en proc.num[] items als het programma naam komt toevallig overeen met een van de threads.

Voordat u parameters in de items proc.mem[] en proc.num[] plaatst, moet u wil misschien de parameters testen met behulp van proc.num[] item en ps opdracht.