一部のプログラムでは、現在のアクティビティを表示する方法としてコマンドラインの変更を使用しています。 ユーザーは、psおよびtopコマンドを実行することでアクティビティを確認できます。 このようなプログラムとしてはPostgreSQL,Sendmail,Zabbixが含まれます。
Linuxでの例を見てみましょう。 いくつかの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 [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 now shows
$ 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 [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_3statusファイルのプロセス名は15文字に切り捨てられます。
同様の結果は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
...明らかにこれは 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"をチェックし、'name'パラメータ値'zabbix_agentd_30'と一致する'zabbix_agentd_30'を取得します。よって、メインプロセスはアイテムproc.num[zabbix_agentd_30,zabbix]によってカウントされます。
次のプロセスをチェックするとき、エージェントはcmdlineファイルからzabbix_agentd_30: collector [idle 1 sec]を取得しようとしますが、nameパラメータがzabbix_agentd_30を満たすことができません。したがって、コマンドラインを変更しないメインプロセスのみがカウントされます。 他のエージェントプロセスはコマンドラインを変更し、無視されます。
このことから今回の例では、プロセスを選択するためにproc.mem[]とproc.num[]でnameパラメータを使用できないことを示しています。
適切な正規表現でcmdlineパラメータを使用すると、正しい結果が得られます。
コマンドラインを変更するプログラムを監視するためにproc.mem[]とproc.num[]の項目を使用するときは注意してください。
nameおよびcmdlineパラメータをproc.mem[]およびproc.num[]アイテムに入れる前に、proc.num[]アイテムおよびpsコマンドを使用してパラメータをテストすることをお勧めします。
proc.mem[]およびproc.num[]項目のcmdlineパラメータでスレッドを選択することはできません例としてカーネルスレッドの1つを上げましょう。
プロセス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.mem[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]'
4157440proc.num []はカーネルスレッドとユーザープロセスの両方をカウントしました。 proc.mem []はユーザープロセスのメモリのみを報告し、カーネルスレッドメモリを0であるかのようにカウントします。これはZBX_NOTSUPPORTEDが報告された上記の場合とは異なります。
プログラム名がスレッドの1つと一致する場合は、proc.mem[]およびproc.num[]アイテムを使用するときに注意してください。
パラメータをproc.mem[]およびproc.num[]アイテムに入れる前に、proc.num[]アイテムとpsコマンドを使用してパラメータをテストすることをお勧めします。