Alguns programes empren la modificació de la seva línia de comandes per mostrar la seva activitat actual. Un usuari pot veure l'activitat executant les comandes ps
i top
. PostgreSQL, Sendmail, Zabbix són exemples d'aquests programes.
Veieu un exemple de Linux. Suposeu que ens cal monitorar un cer nombre de processos d'agent Zabbix.
La comanda ps
mostra els processos que ens calen
$ 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 selecció dels processos per nom d'usuari fan aquesta feina:
Mentrestant, reanomenem l'executable zabbix_agentd
a zabbix_agentd_30
i el reengeguem.
ps
ensenya ara:
$ 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]
...
Mentrestant, la selecció dels processos per nom i usuari produeix un resultat incorrecte:
Per què un simple canvi de nom d'executable cap a un nom més llarg ens porta a un resultat ben diferent?
L'agent Zabbix comença verificant el nom dels processos. L'arxiu /proc/<pid>/status
és obert i la línia Name
marcada. En el nostre cas, les línies de Name
són:
$ 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
El nom dels processos dins l'arxiu status
es retalla a 15 caràcters.
Un resultat semblant es pot veure amb la comanda 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
...
Evidentment, proc.num[]
no és igual al nostre valor del paràmetre name
: zabbix_agentd_30
. Com ha fallat la coincidència del nom de processos de l'arxiu status
, l'agent Zabbix passa al fitxer /proc/<pid>/cmdline
.
Com l'agent veu l'arxiu "cmdline" es pot il·lustrar amb l'execució d'una comanda
$ 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>...
Els arxius /proc/<pid>/cmdline
del nostre cas contenen octets nuls invisibles i no imprimibles, emprats per acabar les cadenes en llenguatge C. Els octets nuls es representen amb "<NUL>" en aquest exemple.
L'agent Zabbix verifica a la "cmdline" el procés principal i pren zabbix_agentd_30
, que correspón al valor del paràmetre name
: zabbix_agentd_30
. Així, el procés principal es compta per l'element 'proc.num[zabbix_agentd_30,zabbix]
.
Quan es verifica el següent procés, l'agent pren zabbix_agentd_30: col·lector [idle 1 sec]
dins l'arxiu cmdline
i no correspon pas al nostre paràmetre name
zabbix_agentd_30
. Així, sobre el procés principal que no modifica pas la línia de comandes, es compta. Altres processos d'agent modifiquen la seva línia de comandes i s'ignoren.
Aquest exemple mostra que el paràmetre name
no pot pas ésser emprat a proc.mem[]
i proc.num[]
per la selecció de processos en aquest cas.
Per a l'element proc.get[]
, quan l'agent Zabbix comprova "cmdline" per al nom del procés, només emprarà una part del nom començant des de la darrera barra i fins al primer espai o signe de dos punts. El nom del procés rebut del fitxer cmdline només s'emprarà si el seu inici coincideix completament amb el nom del procés escurçat del fitxer "estat". L'algorisme és el mateix tant per al nom del procés al filtre com per a la sortida JSON.
L'ús del paràmetre cmdline
amb una expressió regular apropiada produeix un resultat correcte:
Sigueu prudent emprant els elements proc.mem[]
i proc.num[]
per monitorar els programes que modifiquen le seves línies de comandes.
Abans de posar els paràmetres name
i cmdline
dins els elements proc.mem[]
i proc.num[]
, podeu provar els paràmetres amb l'ajuda de l'element proc.num[]
i de la comanda ps
.
cmdline
dins els elements proc.get[]
, proc.mem[]
i proc.num[]
Preneu com a exemple un dels fils del kernel:
Es pot triar amb el paràmetre name
dels processos:
Però amb la selecció per processos, el paràmetre cmdline no funciona pas:
La raó en que l'agent Zabbix pren l'expressió regular especificada al paràmetre cmdline
i l'aplica al contenidor de processos /proc/<pid>/cmdline
. Per als fils de kernel, els fitxers /proc/<pid>/cmdline
són buits. Així, el paràmetre cmdline
no coincidirà mai.
proc.mem[]
i proc.num[]
Els fils de kernel Linux es compten amb l'element proc.num[]
, però no assenyalen pas la memòria de l'element proc.mem[]
. Per 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.
Però què passa si un procés d'usuari porta el mateix nom que un fil de kernel? S'assemblarà a això:
$ 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[]
compta tant els fils de kernel com els processos d'usuari. proc.mem[]
reporta la memòria només per als processos d'usuaris i compta la memòria del fil de kernel com si tingués estat 0. Aquesta és diferent del cas que hi ha aquí dalt, quan ZBX_NOTSUPPORTED ha estat reportat.
Mireu d'ésser prudents quan empreu els elements proc.mem[]
i proc.num[]
si el nom del programa correspon a un dels fils.
Abans d'afegir els paràmetres als elements proc.mem[]
i proc.num[]
, podeu testar amb l'ajuda de l'element proc.num[]
i la comanda ps
.