[comment]: # ({b3f6bc92-c42d1f48})
# 8 Note sulla selezione dei processi negli item proc.mem e proc.num

[comment]: # ({/b3f6bc92-c42d1f48})

[comment]: # ({e9ff6ad6-93778d6f})
#### Processi che modificano la propria command line

Alcuni programmi usano la modifica della propria command line come metodo per visualizzare la loro attività corrente. Un utente può vedere l'attività eseguendo i comandi `ps` e `top`. Esempi di tali programmi includono *PostgreSQL*, *Sendmail*, *Zabbix*.

Vediamo un esempio da Linux. Supponiamo di voler monitorare un numero di processi di Zabbix agent.

Il comando `ps` mostra i processi di interesse come

    $ 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/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 selezione dei processi per nome e utente funziona:

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

Ora rinominiamo l'eseguibile `zabbix_agentd` in `zabbix_agentd_30` e riavviamolo.

`ps` ora mostra

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

Ora la selezione dei processi per nome e utente produce un risultato errato:

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

Perché una semplice rinomina dell'eseguibile con un nome più lungo porta a un risultato così diverso?

Zabbix agent inizia controllando il nome del processo. Viene aperto il file `/proc/<pid>/status` e viene controllata la riga `Name`. Nel nostro caso le righe `Name` sono:

    $ 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

Il nome del processo nel file `status` viene troncato a 15 caratteri.

Un risultato simile si può vedere con il comando `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
     ...

Ovviamente, questo non è uguale al valore del parametro `name` `zabbix_agentd_30` del nostro `proc.num[]`. Non riuscendo a far corrispondere il nome del processo dal file `status`, Zabbix agent passa al file `/proc/<pid>/cmdline`.

Come l'agent vede il file "cmdline" può essere illustrato eseguendo il comando

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

Nel nostro caso i file `/proc/<pid>/cmdline` contengono byte null invisibili e non stampabili, usati per terminare le stringhe nel linguaggio *C*. In questo esempio i byte null sono mostrati come "<NUL>".

Zabbix agent controlla "cmdline" per il processo principale e prende `zabbix_agentd_30`, che corrisponde al valore del nostro parametro `name` `zabbix_agentd_30`. Quindi il processo principale viene conteggiato dall'item `proc.num[zabbix_agentd_30,zabbix]`.

Quando controlla il processo successivo, l'agent prende `zabbix_agentd_30: collector [idle 1 sec]` dal file `cmdline` e questo non corrisponde al nostro parametro `name` `zabbix_agentd_30`. Quindi viene conteggiato solo il processo principale, che non modifica la propria command line. Gli altri processi agent modificano la propria command line e vengono ignorati.

Questo esempio mostra che il parametro `name` non può essere usato in `proc.mem[]` e `proc.num[]` per selezionare i processi in questo caso.

:::noteclassic
Per l'item `proc.get[]`, quando Zabbix agent controlla "cmdline" per il nome del processo, userà solo la parte del nome che inizia dall'ultima barra e termina al primo spazio o ai due punti. Il nome del processo ricevuto dal file cmdline verrà usato solo se il suo inizio corrisponde completamente al nome abbreviato del processo nel file `status`. L'algoritmo è lo stesso sia per il nome del processo nel filtro sia per quello nell'output JSON.
:::

L'uso del parametro `cmdline` con un'espressione regolare appropriata produce un risultato corretto:

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

Prestare attenzione quando si usano gli item `proc.get[]`, `proc.mem[]` e `proc.num[]` per monitorare programmi che modificano le proprie command line.

Prima di inserire i parametri `name` e `cmdline` negli item `proc.get[]`, `proc.mem[]` e `proc.num[]`, può essere utile testare i parametri usando l'item `proc.num[]` e il comando `ps`.

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

[comment]: # ({0ff11097-0ff11097})
#### Thread del kernel Linux

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

[comment]: # ({7212f400-3588d8df})
##### I thread non possono essere selezionati con il parametro `cmdline` negli item `proc.get[]`, `proc.mem[]` e `proc.num[]`

Prendiamo come esempio uno dei thread del kernel:

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

Può essere selezionato con il parametro `name` del processo:

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

Ma la selezione tramite il parametro `cmdline` del processo non funziona:

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

Il motivo è che Zabbix agent prende l'espressione regolare specificata
nel parametro `cmdline` e la applica al contenuto di
`/proc/<pid>/cmdline` del processo. Per i thread del kernel, i file
`/proc/<pid>/cmdline` sono vuoti. Pertanto, il parametro `cmdline` non trova mai corrispondenza.

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

[comment]: # ({8d1ef0a6-8d1ef0a6})
##### Conteggio dei thread negli item `proc.mem[]` e `proc.num[]`

I thread del kernel Linux vengono conteggiati dall'item `proc.num[]`, ma non riportano
memoria nell'item `proc.mem[]`. Per esempio:

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

Ma cosa succede se esiste un processo utente con lo stesso nome di un
thread del kernel? In tal caso potrebbe apparire così:

    $ 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[]` ha conteggiato sia il thread del kernel sia il processo utente.
`proc.mem[]` riporta la memoria solo per il processo utente e considera la
memoria del thread del kernel come se fosse 0. Questo è diverso dal caso
precedente, in cui veniva riportato ZBX\_NOTSUPPORTED.

Prestare attenzione quando si utilizzano gli item `proc.mem[]` e `proc.num[]` se il nome del programma
coincide con quello di uno dei thread.

Prima di inserire parametri negli item `proc.mem[]` e `proc.num[]`, si
consiglia di testare i parametri usando l'item `proc.num[]` e il comando `ps`.

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