シェルスクリプト

【プロセス死活監視シェル】snmpでサーバのプロセス稼働状況を取得し、結果をシステムログに書き込む方法

【シェルスクリプト】snmpでサーバのプロセスを監視し、結果をシステムログに書き込む方法
悩み人

snmpを用いて、サーバのプロセス稼働を死活監視するシェルスクリプトの作り方を知りたい~!

監視するプロセスやサーバの宛先IPアドレスは運用者にて編集しやすいようにしておきたいな。

今回はこのような疑問をお答えします!

本記事の内容
  • snmpにてサーバのプロセス稼働を死活監視し、結果をシステムログに書き込むシェルスクリプトを紹介
  • 「稼働中プロセス名が取得できるMIB」「外部ファイルを読み込む方法(while read)」「snmpwalkコマンドのコツ」といった、重要テクニックを解説
プロフィール画像

【この記事を書いた人】
らいし

30代システムエンジニア
 大手インフラ系企業SV/NW/社内SE経験
資格:応用情報,基本情報,CCNP,CCNA等
6年間Linux系サーバ保守を経験

サーバ監視で最も大切な要素の1つである”プロセス稼働の死活監視”。

システム障害の暫定対策やサーバ監視ソフトウェアサポート切れ等個別にプロセス稼働を死活監視したいシーンありませんか?

悩み人

あるある~!既存のサーバ監視ソフトウェアの設定変更が難しい場合も多いんだよね。

この記事では、メンテナンス性に優れたSNMPを用いたプロセス稼働の死活監視シェルスクリプトを紹介します。
重要テクニックも解説していますので、色んなシーンに応用できる知識も身に付きますよ。

らいし

このシェルスクリプトは実際のSEの現場で使用したものですので、ほぼそのまま使えますよ

プロセス死活監視シェルスクリプトの概要

それでは今回紹介・解説するシェルスクリプトを説明していきます。
それほど難しくないので、気難しく考えなくてOKですよ。

動作概要

今回紹介するスクリプトの処理フローは次のようになります。

  1. 「1:被監視サーバ名」、「2:被監視サーバIPアドレス」、「3:取得プロセス定義ファイル名」が記述されたファイルを1行ずつ読み込み、配列に格納
  2. 事前に被監視サーバにpingを実行し、NGなら以降のsnmp処理はせず、疎通不可の旨をシステムログに書き込む
  3. ①で取得した「3:取得プロセス定義ファイル名」から「1:取得対象プロセス名」と「2:プロセス常時稼働数」を配列格納
  4. 被監視サーバに対してMIB「HOST-RESOURCE-MIB::hrSWRunName」をsnmpwalkで取得し、表示される行数を変数格納
  5. ④で取得したプロセス表示結果と③で取得した「2:プロセス常時稼働数」を比較する
  6. 異なる場合は”異常停止”の旨を、一致した場合は”正常”の旨をloggerコマンドでシステムログに書き込む

MIBとは、SNMPなどで遠隔から機器を監視・管理する際に用いられる、監視対象の機器が自らの設定や状態についてまとめたデータ集合。また、その形式や参照方法について定めた規格。

引用元:MIB 【Management Information Base】 管理情報ベース

被監視サーバ(snmpクライアント)はWindowsでもlinuxでも対応できます

動作確認環境

CentOS Linux release 7.9.2009 (Core)

この記事内では、被監視サーバ(snmpクライアント)のOSはWindowsでテストした結果を記述しております。

プログラムの難易度

【総合評価】
 (普通)


<詳細>
【処理量】
(少ない)
【分岐量】
(普通)
【高度なコマンド】
(普通)

らいし

紹介するプロセス死活監視シェルスクリプトの難易度は難しくもなく、簡単でもなくってところですね

プログラムコード

#!/bin/bash

#------------初期定義--------------#
tooldir=/work/processchk/   #ツールの配置フォルダ
nd_li=${tooldir}nodelist         #被監視サーバリストファイルフルパス
community=public             #被監視サーバ側のコミュニティ名
Getprocdir=${tooldir}getprocesslist/   #取得プロセス定義ファイル保存フォルダ
GetProcOID=1.3.6.1.2.1.25.4.2.1.2  #★1 HOST-RESOURCE-MIB::hrSWRunName プロセス名取得OID

#----------------------------------#


#----------main--------------------#
while read line            #★2【while1】nodelistを読み込み最終行まで処理する
do
  par=($line)  #配列に格納

 ###事前にpingを実行し、NGならSNMP処理しない####
   ping ${par[1]} -c 3 -w 3 > /dev/null 2>&1
  if [ $? = 0 ] ;then  ##ping成功

  while read Proc_info     #【while2】取得プロセス定義ファイルを読み込み最終行まで処理する
  do
   Proc_par=($Proc_info)  #配列に格納


  ######SNMP取得処理############
   ProcGet_res=`snmpwalk -v 2c -c $community ${par[1]} $GetProcOID |grep ${Proc_par[0]}  | wc -l` #★3

   #説明:nodelistで定義されるIPアドレス、OIDでsnmpwalkし、取得プロセス名でgrepし、表示される行数を変数格納##
  ##############################


  #######アラート通知##########
  if [ $ProcGet_res -ne ${Proc_par[1]}  ];then  ##プロセス取得結果と取得プロセス定義ファイルの常時稼働数を比較
   logger -p syslog.error "${par[0]}${Proc_par[0]}プロセスが異常停止しています。(稼働数 通常:${Proc_par[1]} 現在:${ProcGet_res})"

  else
    logger -p syslog.info "${par[0]}${Proc_par[0]}プロセスは正常です。"
  fi  
  ##############################

  done < $Getprocdir${par[2]}  #【while2のdone】

  ###############pingNGなら以下を処理##########
  else
   logger -p syslog.error "${par[0]}に対するプロセス稼働チェックをしようとしましたが疎通ができませんでした"
  fi

done < $nd_li  #【while1のdone】被監視サーバリストファイルを指定
  • 転用する場合はパラメータ内の各変数をお好みの値に変更したうえでお使いください
  • テクニック解説するコードは「★+数値」で表記しています

プログラム利用前の準備事項

らいし

今回紹介したプロセス死活監視シェルスクリプトを実行するためにはちょっとだけ事前準備が必要です

①次のコマンドを実行し、プログラム実行に必要となるディレクトリを作成してください。

mkdir /work/processchk/
mkdir /work/processchk/getprocesslist

②次の例を参考に被監視サーバリストファイルを作成し、/work/processchk/に配置してください。

[root@centos7 processchk]# cat nodelist 
sv1-1name_ 192.168.0.20 sv1
sv1-2name_ 192.168.0.99 sv1

左から「被監視サーバ名(loggerコマンド用のため漢字でもOK」、被監視サーバIPアドレス、取得プロセス定義ファイル名」になります。

「logger」コマンドとは、システムログに指定した内容の行を追加するコマンドです

③次の例を参考に取得プロセス定義ファイルを作成し、/work/processchk/getprocesslist/に配置してください。

[root@centos7 getprocesslist]# cat sv1 
VBoxSDS.exe 1
dns.exe 1
sshd.exe 1

左から「取得プロセス名、常時稼働数」になります。取得プロセス名は事前に以下のようにsnmpwalkを実行し、表示されるプロセス名を確認したうえで記述してください。

[root@centos7 processchk]# snmpwalk -v 2c -c public 192.168.0.20 1.3.6.1.2.1.25.4.2.1.2
(中略)
HOST-RESOURCES-MIB::hrSWRunName.584 = STRING: "Cortana.exe"  ←Cortana.exeがプロセス名
(以下省略)

”取得プロセス定義ファイル”のファイル名は②”被監視サーバリストファイル”で記述した「取得プロセス定義ファイル名」と一致するようにしてください。

④被監視サーバにsnmpクライアントの設定をしてください。

snmpサービス設定は「管理者で実行」で管理画面を開かないとセキュリティタブが表示されませんので注意が必要です

プログラム実行結果

[root@centos7 processchk]# ./processchk.sh 
[root@centos7 processchk]# tail /var/log/messages
Feb 18 23:19:45 centos7 root: sv1-1name_VBoxSDS.exeプロセスは正常です。
Feb 18 23:19:46 centos7 root: sv1-1name_dns.exeプロセスが異常停止しています。(稼働数 通常:1 現在:0)
Feb 18 23:19:46 centos7 root: sv1-1name_sshd.exeプロセスが異常停止しています。(稼働数 通常:1 現在:0)
Feb 18 23:19:49 centos7 root: sv1-2name_に対するプロセス稼働チェックをしようとしましたが疎通ができませんでした
らいし

各プロセスが正常か異常停止しているかチェックできていますね

重要テクニック解説

さて、ここからは紹介したプログラムコードの中で、特に着目したい重要テクニックを解説していきます。
紹介するテクニックは、今回のプログラムだけではなく、色んなシーンで応用できるものになりますので必見です。

「HOST-RESOURCE-MIB::hrSWRunName」について

GetProcOID=1.3.6.1.2.1.25.4.2.1.2

「HOST-RESOURCE-MIB::hrSWRunName(OID:1.3.6.1.2.1.25.4.2.1.2)」は現在稼働中のプロセス名の一覧を出力する標準MIBの1つです。

標準MIBとはRFCによって定義された業界標準の規格です。各ベンダーで共通で利用することができ、どのメーカーの機器であっても、標準MIBを介することで画一的な情報の交換が可能になります。なお、現在の標準MIBとして位置づけられているのは「MIB-2」です。

引用元:こっそり聞きたいネットワークのキホン(第27回) ネットワーク機器が持つMIBについて解説

今回肝となるプロセスが稼働中かどうかを判断するために使用します。
実際のsnmpwalkの実行結果は次のとおりです。

[root@centos7 processchk]# snmpwalk -v 2c -c public 192.168.0.20 1.3.6.1.2.1.25.4.2.1.2
HOST-RESOURCES-MIB::hrSWRunName.1 = STRING: "System Idle Process"
HOST-RESOURCES-MIB::hrSWRunName.4 = STRING: "System"
HOST-RESOURCES-MIB::hrSWRunName.100 = STRING: "Registry"
HOST-RESOURCES-MIB::hrSWRunName.360 = STRING: "msedge.exe"
HOST-RESOURCES-MIB::hrSWRunName.400 = STRING: "smss.exe"
HOST-RESOURCES-MIB::hrSWRunName.564 = STRING: "csrss.exe"
HOST-RESOURCES-MIB::hrSWRunName.584 = STRING: "Cortana.exe"
(以下省略)

このMIBの大きな特徴は次のとおりです。

  • 同一名のプロセスが複数稼働している場合は稼働数分、表示される
  • 停止しているプロセスは表示されない
らいし

この特性を利用すればプロセス稼働状況の死活監視ができそうですね

「while read 変数 do~ done < ファイル名」について

while read 変数 
do
 ###実行コマンド###
done <  ファイル名

while文とは「条件が満されている間、その処理を繰り返す」制御文です。

”while read 変数”にすることによって、指定した外部ファイルの一行目から順番に値を読み込み、変数に格納したうえで、while文内の処理を実行するという優れもの。

一行目が終わったら、二行目の値を読み込んで再度while文を実行という流れで、最後まで処理したらwhile文を抜けます。

今回外部ファイルには以下要素を管理し、行読み込み都度、配列に格納するようにしています。

読み込みファイル:被監視サーバリストファイル

格納配列名:par[]

  • 被監視サーバ名=par[0]
  • IPアドレス=par[1]
  • 取得プロセス定義ファイル名=par[2]

読み込みファイル:取得プロセス定義ファイル

格納配列名:Proc_par

  • 取得プロセス名=Proc_par[0]
  • 常時稼働数=Proc_par[1]

こういった要素は運用していく中で、増えたり、減ったりしますよね?外部ファイルで管理することで、容易に編集・管理することができます。

本体プログラムの中に、運用によって可変する頻度が高いパラメータを直接書く行為はセンスがないのでやめましょう。

「while read 変数」文は非常に応用性が高く、今回紹介するプロセス稼働死活監視用途以外にも、「pingを宛先IPアドレスファイルを読み込みながら実行し記録するスクリプト」でも活用していますのでよかったらご覧ください。

シェルスクリプト
【ping死活監視シェル】宛先IPアドレスファイルを読み込みながらpingを実行し記録する方法シェルスクリプトでpingツールを作りたい方は必見!この記事では外部ファイルで定義された宛先IPアドレスを読み取りながらpingを実行し記録するシェルスクリプトを紹介します。とても簡単で重要テクニックの解説もあり!これは私が実際のSE現場で作成し活躍したものになります。...

snmpwalkコマンド | grepコマンド | wc -l について

  ProcGet_res=`snmpwalk -v ”バージョン名” -c ”コミュニティ名” ”IPアドレス” ”OID" |grep ”取得プロセス名”  | wc -l` 

この1行で3つのコマンドを組み合わせています。

1つずつ解説していきます。

snmpwalkコマンドとは

”snmpwalk”は指定した宛先IPアドレス・MIBに対して、snmp通信を行い、MIB値を取得するものです。

他にもsnmpgetコマンドやsnmpgetnextコマンド等類似するものがありますが、今回は複数のMIBを一括取得できるsnmpwalkを利用します。

らいし

このコマンドは私が勤めていた会社で最も利用した、思い入れのあるコマンドです

またsnmpwalkコマンドにはv1,v2c,v3の3種類からバージョン指定が必要ですが、今回は最も扱いやすいv2cを利用します。

snmpwalkコマンドの書式

snmpwalk -v 2c -c <コミュニティ名> <通信相手> < OID >

< OID >を省略すると標準MIBを全て取得する処理になります。

snmpwalkコマンドのオプション

バージョン指定オプション”-v”、コミュニティ名指定オプション”-c”以外にもオプションはありますので参考に記載しておきます。

オプション意味
-VNet-SNMPのバージョンを表示します
-r試行回数を指定します。
-tリクエストのタイムアウト時間を秒で指定します。
-d通信されたパケットを16進数で出力してデバッグに使用します。

引用元:snmpwalkの使い方は?snmpwalkコマンドの使用方法を徹底解説

grepコマンドの活用

grepコマンドとはファイルから特定の文字列が存在するかを調べたいときに利用されるLinuxコマンドです。

らいし

数あるコマンドの中でも、最重要コマンドの1つです!

snmpwalkコマンドだけ、稼働しているプロセス全てが表示されてしまいます。

そこで”grep プロセス名”で稼働状況を確認したいプロセス名だけを表示し、対象を絞ります。

wc -lとは

wcコマンドとはテキストファイルの行数や単語数、文字数を数えるコマンドです。

オプション-lは改行の数を表示します。

snmpwalk + grepコマンドの組み合わせだけでは、残念ながら目的は達成しないのでさらにもう一工夫です。

今回使うMIB(HOST-RESOURCE-MIB::hrSWRunName)はプロセス名を取得するものですが、本来知りたいことはプロセスの稼働数です。

そこで”wc -l”コマンドです。

wcコマンドのオプション

オプション意味
-cバイト数を表示する
-m文字数を表示する(マルチバイト文字に対応)
-l 改行の数を表示する
-w単語数を表示する
-L最も長い行の長さを表示する

引用元:【 wc 】コマンド――テキストファイルの文字数や行数を数える

wcコマンドは今回のように他コマンドと複合した形で利用すると便利で、-lオプションにより”他コマンドにより表示される行数”を返します。

この行数というのが現在稼働しているプロセス数そのものになります。

この数をチェックすればプロセス死活監視ができます。

snmpwalk & grepにより1行表示=返り値:1=稼働プロセス数:1といった具合です。

悩み人

ここまで学んできたが、やっぱりもう少し基礎からシェルについて勉強が必要だな~

そんな方のためにLinuxのことが学べるオススメの参考書を紹介しておきます。
初心者に優しく補足説明もしっかり入っており、入門者にはピッタリです。
これらは購入者も多く、人気の参考書です。

¥2,970 (2022/02/25 23:39時点 | Amazon調べ)

実際のSE現場で活躍した時の状況

idea


私の会社では複数のサーバ(以降、被監視サーバ)を所管・運用しており、これらサーバのプロセス監視方法は、とあるベンダーのサーバ監視用パッケージソフトウェア(以降、サーバ監視ソフト)のエージェントを被監視サーバへインストールし、死活監視していました。

ある日、特定の被監視サーバのリプレースが必要になり、OSを

Windows Server 2008→Windows Server 2016

へ変更することになりました。

すると、サーバ監視ソフトのバージョンアップが必要となることがわかり、パッケージライセンスにより、非常に大きなコストとバージョンアップ作業工数がかかることがわかりました。

  • 今回リプレースする被監視サーバで監視したいプロセスは数個しかなかった
  • このサーバのSLA上、それほど精度の高いプロセス監視をしなくても良い要件
  • サーバ監視ソフトを実装しているサーバのリプレースも近々計画されていた


以上の理由から、コスト削減のため、今回のスクリプトを自ら作成しました。

良く言えば、コスト削減。悪く言えば、手を抜いた、というわけです。

今回は以上です。今回のシェルスクリプトは結構幅広く実務で使えるシェルではないでしょうか?私と同じ境遇でお困りの方の参考になれば幸いです。