Неки програми користе модификацију своје командне линије као метод за приказивање њихове тренутне активности. Корисник може да види активност покретањем ps
и top
команде. Примери таквих програма укључују PostgreSQL, Sendmail, Zabbix.
Погледајмо пример из Linux-a. Претпоставимо да желимо да надгледамо број процеса Zabbix агента.
Команда ps
приказује процесе од интереса као
$ ps -fu zabbix
UID PID PPID C STIME TTYTIME 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]
...
Избор процеса по имену и кориснику обавља посао:
Сада преименујмо извршну датотеку zabbix_agentd
у zabbix_agentd_30
и поново покренимо.
ps
сада приказује
$ ps -fu zabbix
UID PID PPID C STIME TTYTIME 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]
...
Сада одабир процеса по имену и кориснику даје нетачан резултат:
Зашто једноставно преименовање извршног фајла у дуже име доводи до прилично другачијег резултата?
Zabbix агент почиње са провером имена процеса. /proc/<pid>/status
датотека се отвара и линија Name
је означена. У нашем случају Name
линије су:
$ 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
Име процеса у датотеци status
је скраћено на 15 карактера.
Сличан резултат се може видети са командом ps
:
$ ps -u zabbix
PID TTYTIME 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
...
Очигледно, то није једнако нашој вредности параметра proc.num[]
name
zabbix_agentd_30
. Пошто није успео да се подудара са именом процеса из status
датотеке коју Zabbix агент претвара у /proc/<pid>/cmdline
датотеку.
Како агент види датотеку "cmdline" може се илустровати покретањем команда
$ 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>...
/proc/<pid>/cmdline
датотеке у нашем случају садрже невидљиве, нештампане нулте бајтове, који се користе за завршавање стрингова у C језику. Нулти бајтови су приказани као "<NUL>" у овом примеру.
Zabbix агент проверава "cmdline" за главни процес и узима zabbix_agentd_30
, који одговара нашој вредности параметра name
zabbix_agentd_30
. Дакле, главни процес се рачуна по ставкама proc.num[zabbix_agentd_30,zabbix]
.
Приликом провере следећег процеса, агент узима `zabbix_agentd_30: collector [idle 1 sec] из датотеке
cmdlineи не испуњава наш параметар
namezabbix_agentd_30`. Дакле, само се рачуна главни процес који не мења своју командну линију. Остали агентски процеси мењају своју командну линију и игноришу се.
Овај пример показује да параметар name
не може да се користи у proc.mem[]и
proc.num[]` за избор процеса у овом случају.
За proc.get[]
ставку, када Zabbix агент провери "cmdline" за име процеса, користиће само део имена почевши од последње косе црте па до првог знака размака или двотачке. Име процеса примљено из cmdline датотеке ће се користити само ако се његов почетак у потпуности поклапа са скраћеним именом процеса у датотеци status
. Алгоритам је исти за име процеса у филтеру и за JSON излаз.
Коришћење параметра cmdline
са одговарајућим регуларним изразом производи тачан резултат:
Будите пажљиви када користите ставке proc.get[]
, proc.mem[]
и proc.num[]
за надгледање програма који модификују своје командне линије.
Пре него што ставите параметре name
и cmdline
у ставке proc.get[]
, proc.mem[]
и proc.num[]
, можда ћете желети да тестирате параметре користећи proc.num[]
item и ps
команде.
cmdline
у ставкама proc.get[]
, proc.mem[]
и proc.num[]
Узмимо као пример једну од нити језгра:
Може се изабрати помоћу параметра name
процеса:
Али избором параметра cmdline
процес не ради:
Разлог је тај што Zabbix агент узима наведени регуларни израз у параметру cmdline
и примењује га на садржај процеса /proc/<pid>/cmdline
. За нити кернела њихове /proc/<pid>/cmdline
датотеке су празне. Дакле, параметар cmdline
се никада не подудара.
proc.mem[]
и proc.num[]
ставкамаНити Linux кернела се броје према proc.num[]
ставки, али се не извештава меморија у ставци proc.mem[]
. на пример:
$ 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.num[kthreadd]'
ZBX_NOTSUPPORTED: Cannot get amount of "VmSize" memory.
Али шта се дешава ако постоји кориснички процес са истим именом као кернел нит? Тада би то могло изгледати овако:
$ 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[]
је бројао и нит кернела и кориснички процес. proc.mem[]
пријављује меморију само за кориснички процес и броји меморију нити кернела као да је 0. Ово се разликује од случаја изнад када је пријављен ZBX_NOTSUPPORTED.
Будите пажљиви када користите ставке proc.mem[]
и proc.num[]
ако се име програма случајно подудара са једном од нити.
Пре него што ставите параметре у ставке proc.mem[]
и proc.num[]
, можда желите да тестирате параметре користећи ставку proc.num[]
item и ps
команду.