一部のプログラムでは、現在のアクティビティを表示する方法としてコマンドラインの変更を使用しています。 ユーザーは、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_3
status
ファイルのプロセス名は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]'
4157440
proc.num []
はカーネルスレッドとユーザープロセスの両方をカウントしました。 proc.mem []
はユーザープロセスのメモリのみを報告し、カーネルスレッドメモリを0であるかのようにカウントします。これはZBX_NOTSUPPORTEDが報告された上記の場合とは異なります。
プログラム名がスレッドの1つと一致する場合は、proc.mem[]
およびproc.num[]
アイテムを使用するときに注意してください。
パラメータをproc.mem[]
およびproc.num[]
アイテムに入れる前に、proc.num[]
アイテムとps
コマンドを使用してパラメータをテストすることをお勧めします。