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.