8 Напомене о одабиру процеса у proc.mem и proc.num ставкама

Процеси који мењају своју командну линију

Неки програми користе модификовање своје командне линије као метод за приказивање своје тренутне активности. Корисник може видети активност покретањем команди ps и top. Примери таквих програма укључују PostgreSQL,Sendmail, Zabbix.

Погледајмо пример из Линукса. Претпоставимо да желимо да пратимо одређени број процеса Zabbix агента.

Команда ps приказује процесе од интереса као

$ 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 [мировање 1 сек] zabbix 6320 6318 0 12:01 ? 00:00:00 sbin/zabbix_agentd: listener #1 [чека се веза] zabbix 6321 6318 0 12:01 ? 00:00:00 sbin/zabbix_agentd: слушалац #2 [чека се веза] zabbix 6322 6318 0 12:01 ? 00:00:00 sbin/zabbix_agentd: слушалац #3 [чека се веза] zabbix 6323 6318 0 12:01 ? 00:00:00 sbin/zabbix_agentd: активне провере #1 [мировање 1 сек]

...

Избор процеса по имену и кориснику обавља посао:

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

Сада преименујемо извршну датотеку zabbix_agentd у zabbix_agentd_30 и поново је покренемо.

ps сада приказује

$ 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 [неактиван 1 сек] zabbix 6717 6715 0 12:53 ? 00:00:00 sbin/zabbix_agentd_30: listener #1 [чекање на везу] zabbix 6718 6715 0 12:53 ? 00:00:00 sbin/zabbix_agentd_30: listener #2 [чекање на везу] zabbix 6719 6715 0 12:53 ? 00:00:00 sbin/zabbix_agentd_30: listener #3 [чекање на везу] zabbix 6720 6715 0 12:53 ? 00:00:00 sbin/zabbix_agentd_30: active checks #1 [неактиван 1 сек] ...

Сада одабир процеса по имену и кориснику даје погрешан резултат:

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

Зашто једноставно преименовање извршне датотеке у дуже име доводи до сасвим другачијег резултата?

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(//,"<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 датотеке и то се не подудара са нашим параметром name zabbix_agentd_30. Дакле, рачуна се само главни процес који не мења своју командну линију. Остали агентски процеси мењају своју командну линију и игноришу се.

Овај пример показује да се параметар name не може користити у proc.mem[] и proc.num[] за избор процеса у овом случају.

За ставку proc.get[], када Zabbix агент проверава „cmdline“ за име процеса, користиће само део имена почевши од последње косе црте и до првог размака или знака двотачке. Име процеса примљено из cmdline датотеке користиће се само ако се његов почетак потпуно подудара са скраћеним именом процеса у status датотеци. Алгоритам је исти и за име процеса у филтеру и у JSON излазу.

Коришћење параметра cmdline са одговарајућим регуларним изразом даје исправан резултат:

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

Будите опрезни када користите ставке proc.get[], proc.mem[] и proc.num[] за праћење програма који мењају своје командне линије.

Пре него што ставите параметре name и cmdline у ставке proc.get[], proc.mem[] и proc.num[], можда ћете желети да тестирате параметре користећи ставку proc.num[] и команду ps.

Linux kernel threads

Нити се не могу изабрати параметром cmdline у ставкама proc.get[], proc.mem[] и proc.num[]

Узмимо као пример једну од нити језгра:

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

Може се изабрати помоћу параметра name процеса:

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

Али избором параметра cmdline процес не ради:

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

Разлог је тај што Zabbix агент узима наведени регуларни израз у параметру cmdline и примењује га на садржај процеса /proc/<pid>/cmdline. За нити кернела њихове /proc/<pid>/cmdline датотеке су празне. Дакле, параметар cmdline се никада не подудара.

Бројање нити у ставкама proc.mem[] и proc.num[]

Нити Linux кернела се броје помоћу ставке proc.num[], али се не приказује меморија у ставци proc.mem[]. На пример:

$ ps -ef | grep kthreadd root200 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: Не може се добити количина меморије "VmSize".

Али шта се дешава ако постоји кориснички процес са истим именом као нит кернела? Тада би то могло изгледати овако:

$ ps -ef | grep kthreadd root200 09:51 ?00:00:00 [kthreadd] zabbix961161330 17:58 pts/100: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[] и команду ps.