Неки програми користе модификовање своје командне линије као метод за приказивање своје тренутне активности. Корисник може видети активност покретањем команди 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
.
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 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
.