8 Piezīmes par procesu atlasi proc.mem un proc.num vienumos

Procesi, kas modificē savu komandrindu

Dažas programmas izmanto savas komandrindas modificēšanu kā metodi, lai attēlotu savu pašreizējo aktivitāti. Lietotājs var redzēt aktivitāti, palaižot ps un top komandas. Šādu programmu piemēri ir PostgreSQL, Sendmail, Zabbix.

Apskatīsim piemēru no Linux. Pieņemsim, ka vēlamies uzraudzīt Zabbix aģenta procesu skaitu.

Komanda ps parāda interesējošos procesus šādi:

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

Procesu atlase pēc nosaukuma un lietotāja darbojas:

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

Tagad pārdēvēsim izpildāmo failu zabbix_agentd par zabbix_agentd_30 un restartēsim to.

Tagad ps parāda:

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

Tagad procesu atlase pēc nosaukuma un lietotāja dod nepareizu rezultātu:

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

Kāpēc vienkārša izpildāmā faila pārdēvēšana uz garāku nosaukumu rada tik atšķirīgu rezultātu?

Zabbix aģents sāk ar procesa nosaukuma pārbaudi. Tiek atvērts fails /proc/<pid>/status un pārbaudīta rinda Name. Mūsu gadījumā Name rindas ir šādas:

$ 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

Procesa nosaukums failā status tiek saīsināts līdz 15 rakstzīmēm.

Līdzīgu rezultātu var redzēt ar komandu 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
 ...

Acīmredzot tas nav vienāds ar mūsu proc.num[] parametra name vērtību zabbix_agentd_30. Tā kā neizdevās saskaņot procesa nosaukumu no faila status, Zabbix aģents pāriet pie faila /proc/<pid>/cmdline.

To, kā aģents redz failu "cmdline", var ilustrēt, palaižot komandu:

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

Faili /proc/<pid>/cmdline mūsu gadījumā satur neredzamus, nedrukājamus nulles baitus, kas C valodā tiek izmantoti virkņu terminēšanai. Šajā piemērā nulles baiti ir parādīti kā "<NUL>".

Zabbix aģents pārbauda "cmdline" galvenajam procesam un iegūst zabbix_agentd_30, kas atbilst mūsu parametra name vērtībai zabbix_agentd_30. Tāpēc galvenais process tiek ieskaitīts ar vienumu proc.num[zabbix_agentd_30,zabbix].

Pārbaudot nākamo procesu, aģents no faila cmdline iegūst zabbix_agentd_30: collector [idle 1 sec], un tas neatbilst mūsu parametram name zabbix_agentd_30. Tāpēc tiek ieskaitīts tikai galvenais process, kas nemodificē savu komandrindu. Citi aģenta procesi modificē savu komandrindu un tiek ignorēti.

Šis piemērs parāda, ka parametru name šajā gadījumā nevar izmantot proc.mem[] un proc.num[] procesu atlasei.

Vienumam proc.get[], kad Zabbix aģents pārbauda procesa nosaukumu laukā "cmdline", tas izmantos tikai to nosaukuma daļu, kas sākas no pēdējās slīpsvītras un turpinās līdz pirmajai atstarpei vai kolam. Procesa nosaukums, kas iegūts no cmdline faila, tiks izmantots tikai tad, ja tā sākums pilnībā atbilst saīsinātajam procesa nosaukumam failā status. Algoritms ir vienāds gan procesa nosaukumam filtrā, gan JSON izvadē.

Izmantojot parametru cmdline ar atbilstošu regulāro izteiksmi, tiek iegūts pareizs rezultāts:

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

Esiet uzmanīgi, izmantojot proc.get[], proc.mem[] un proc.num[] vienumus, lai uzraudzītu programmas, kas modificē savas komandrindas.

Pirms ievietot parametrus name un cmdline vienumos proc.get[], proc.mem[] un proc.num[], iespējams, vēlēsieties pārbaudīt šos parametrus, izmantojot vienumu proc.num[] un komandu ps.

Linux kodola pavedieni

Pavedienus nevar atlasīt ar cmdline parametru proc.get[], proc.mem[] un proc.num[] vienumos

Apskatīsim kā piemēru vienu no kodola pavedieniem:

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

To var atlasīt ar procesa name parametru:

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

Taču atlase pēc procesa cmdline parametra nedarbojas:

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

Iemesls ir tāds, ka Zabbix aģents ņem regulāro izteiksmi, kas norādīta cmdline parametrā, un piemēro to procesa /proc/<pid>/cmdline saturam. Kodola pavedieniem to /proc/<pid>/cmdline faili ir tukši. Tāpēc cmdline parametrs nekad neatbilst.

Pavedienu skaitīšana proc.mem[] un proc.num[] vienumos

Linux kodola pavedieni tiek skaitīti ar proc.num[] vienumu, taču tie neziņo par atmiņu proc.mem[] vienumā. Piemēram:

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

Bet kas notiek, ja ir lietotāja process ar tādu pašu nosaukumu kā kodola pavedienam? Tad tas varētu izskatīties šādi:

$ 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[] saskaitīja gan kodola pavedienu, gan lietotāja procesu. proc.mem[] ziņo par atmiņu tikai lietotāja procesam un uzskata kodola pavediena atmiņu par 0. Tas atšķiras no iepriekšējā gadījuma, kad tika ziņots ZBX_NOTSUPPORTED.

Esiet piesardzīgi, izmantojot proc.mem[] un proc.num[] vienumus, ja programmas nosaukums nejauši sakrīt ar kāda pavediena nosaukumu.

Pirms parametru ievietošanas proc.mem[] un proc.num[] vienumos, iespējams, vēlēsieties pārbaudīt parametrus, izmantojot proc.num[] vienumu un komandu ps.