特定の時間が経過したプロセスの数を Zabbix で監視する

morikawaawk,process,Zabbix,経過時間

久しぶりの投稿になります。インフラグループの Morikawa です。
Labs の執筆推進のメンバーなのですがここ数ヶ月更新が滞っておりすいません。

前回の kamo さんの記事投稿で昨年 6 月頃にスタートした Labs 再開プロジェクトが一周しまして、また次の一周をスタートする準備を進めているところです。

今回は再び Zabbix による監視ネタになります。大したものではないのですが、意外に検索しても見つからない情報だったので役に立つ方には役に立つのではないかと。

今回監視したいのは 特定の時間が経過したプロセスの数 です。デーモンなど長期間動作していて当然のプロセスは問題ないのですが、バッチ系の処理を行っているサーバ上で、そのバッチ処理プロセスが残ったままになってしまう、という経験はおありの方もいるのではないでしょうか。もちろんバッチ処理を見なおして残ったままにしないよう改修するのが根本的な良い解決方法となりますが、とりあえずそういった状況を自動検知したいというニーズはあるかと思います。今回はそれを Zabbix にやらせようという話です。

とりあえずサクッと導入できちゃう設定編と、その内容の解説編とに分けて紹介します。

設定編

監視されるサーバ側での設定

Zabbix Agent の設定ファイルである zabbix_agentd.conf か、もしくはそのファイルからインクルードされるファイルなどに以下の UserParameter を記載しましょう。ちなみにこれの動作確認は CentOS で行ってます。

UserParameter=custom.proc.elapsed.num[*],/bin/ps -eo user:32,etime,command | grep -F "$3" | awk '$(1) == "$2" || "$2" == "" {print $(2)}' | sed 's/:\|-/ /g;' | awk '{print $(4)" "$(3)" "$(2)" "$(1)}' | awk 'BEGIN { x=0 ; if ("$1" == "") {min=-1} else {min="$1"+0} } {if ($(1)+$(2)*60+$(3)*3600+$(4)*86400 > min) x+=1 } END {print x}'

Zabbix Server 側でのアイテムの設定

Zabbix Server 側のアイテムの設定では、キーに以下を設定します。

custom.proc.elapsed.num[<ELAPSED_SEC>,<USER>,<CMDLINE>]

ELAPSED_SEC がプロセスの経過時間、USER がプロセスの実行ユーザ、CMDLINE がコマンドラインに含まれる文字列となり、最初の ELAPSED_SEC で指定する秒数よりも長く動作しているプロセスの数が整数値として得られます。

具体的には以下のようになりますね。root で起動していて “sshd:" という文字列を含み 86400 秒以上経過したプロセスの数が取得されます。

custom.proc.elapsed.num[86400,root,"sshd:"]

ちなみに ELAPSED_SEC, USER, CMDLINE はそれぞれ省略可能で、ELAPSED_SEC は -1 秒以上 (つまり全てのプロセスが対象)、USER は全てのユーザが対象、CMDLINE はあらゆるコマンドを対象とすることになります。

Zabbix Server 側でのトリガーの設定

後はトリガーの設定さえ行えば自動検知が可能になります。閾値は対象に応じて様々ですが、例えば上記の例に出したアイテムで取得した数が 1 以上の場合にアラートを上げたいのであれば、トリガーには以下のように設定すれば OK です。

{custom.proc.elapsed.num[86400,root,"sshd:"].last(0)}>0

以上で設定は完了です。

解説編

さて、こちらは特に UserParameter の内容についての解説編になります。上記で UserParameter で指定した内容を改行で見やすく表示してみます。

UserParameter=custom.proc.elapsed.num[*],
  /bin/ps -eo user:32,etime,command 
  | grep -F "$3" 
  | awk '$(1) == "$2" || "$2" == "" {print $(2)}' 
  | sed 's/:\|-/ /g;' 
  | awk '{print $(4)" "$(3)" "$(2)" "$(1)}' 
  | awk '
    BEGIN 
    { 
      x=0 ; 
      if ("$1" == "") {
        min=-1
      } else {
        min="$1"+0
      } 
    } 
    {
      if ($(1)+$(2)*60+$(3)*3600+$(4)*86400 > min) x+=1 
    } 
    END 
    {
      print x
    }'

ps コマンドに上記オプション -eo user:32,etime,command をつけると、以下の様なフォーマットでプロセス情報が取得されます。

apache     5-17:24:45 /usr/sbin/httpd
root     120-02:31:51 smbd
postfix         52:05 pickup -l -t fifo -u

grep で CMDLINE に指定した内容で絞込み、その次の awk で USER で指定した内容で絞り込んで、時間のみ表示させて次に渡します。なお、 USER を省略した際に全てのユーザを対象にするように || “$2" == “" が入ってます。

次に sed で時刻部分の “-" および “:" を空白にすることで、例えば上記の出力は以下のようになります。

  5 17 24 45
120 02 31 51
       52 05

それを awk の “{print $(4)" “$(3)" “$(2)" “$(1)}" で左右をひっくり返して表示させます。

45 24 17   5
51 31 02 120
05 52

最後に、awk の “$(1)+$(2)*60+$(3)*3600+$(4)*86400" で、秒数に置き換えます。空文字は awk は 0 扱いするため、結果は正しくなります。後はその置き換えた数値と ELAPSED_SEC を比較し、前者のほうが大きいものをカウントして数値として返すという挙動になります。BEGIN の中身は、主に ELAPSED_SEC 省略時に文法エラーを生じさせないための処理です。

ちなみに、このひっくり返してから秒・分・時・日を秒に換算するという計算方法はもちろん(?)私のアイディアではなく、Parse ps etime output into seconds にて紹介されていた内容です。見た時は目からウロコでした。

なお、気になる方は気になったかと思いますが、一般に awk では引数を $1, $2, … と表現しますが、$(1), $(2) としていますね。これは $1, $2 が Zabbix の UserParameter の引数としても扱われるため、普通に $1 などと書くとそちらで置換されてしまうためです。awk の引数は Zabbix 側に置換されない $(1) という表記にしています。

まとめ

さて、今回は簡単でしたが、経過時間で判定させたプロセス数の監視について記事にしてみました。awk、grep、sed などと監視ツールを組み合わせるとかなり柔軟に何でも監視できちゃいますね。要望がどれくらいあるかは分かりませんが、お役に立てば幸いです。

ちょっと早いですが、皆さん良いお年を!

morikawaawk,process,Zabbix,経過時間

Posted by morikawa