シェルスクリプト

【ping死活監視シェル】宛先IPアドレスファイルを読み込みながらpingを実行し記録する方法

シェルスクリプト
悩み人

外部ファイルの読み込み、ログローテーションといった、メンテナス性の優れたping死活監視シェルスクリプトの作り方を知りたい~!

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

本記事の内容
  • 宛先IPアドレスリストを読み込み、pingの実行結果をファイルに残すシェルスクリプトを紹介
  • 「外部ファイルを読み込む方法(while read)」「pingコマンドのコツ」「特殊変数」といった、重要テクニックを解説
プロフィール画像

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

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

サーバやネットワーク保守を担当していると、システムの障害原因切り分け対応のため、pingコマンドにより長期的に疎通結果を管理したいシーンありませんか?

悩み人

あるある~!セキュリティレベルの高いクローズなシステムだと、フリーソフトとか使えないんだよね。

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

らいし

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

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

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

動作概要

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

  1. 宛先IPアドレス一覧ファイルを1行ずつ読み込み、変数格納
  2. ①で格納した変数を用いてpingを実行し、結果をファイルにリダイレクト
    (最終行まで①~②を繰り返し)
  3. 指定した過去日付ファイルを消す

動作確認環境

CentOS Linux release 7.9.2009 (Core)

プログラムの難易度

【総合評価】
 優しい


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

らいし

紹介するping死活監視シェルスクリプトは複雑な処理は全くしていません

プログラムコード

#!/bin/sh

##パラメータ(必要に応じて値を変更)###############
counter=1 #pingを何回実行するか
waittime=2 #ping応答待ち時間(秒)
logrmday=1 #何日前の日付ファイルを削除するか指定
logfilename="_ping_result.csv" #ping実行結果を記録するファイル名
tool_dir=/work/pingtool/ #このツールを配置するディレクトリ
res_dir=/work/pingtool/result/  #実行結果ファイルを保存するディレクトリ 
iplist=iplist.txt #宛先IPアドレス一覧ファイル
############################

##初期定義###################
TODAY=`date +%Y%m%d`  #現在時刻をあらかじめ変数格納
clfilename=$TODAY$logfilename #処理時の実行結果ファイル名

del=`date +%Y%m%d -d "$logrmday days ago"`  #自動削除する時刻を$logrmdayから逆算して変数格納
delfilename=$del$logfilename #自動削除する実行結果ファイル名
#############################

#####メイン##################
while read line  #★1 宛先IPアドレス一覧ファイルを一行ずつ読み出し,$lineに格納したうえで実行
do
 DATESTR=`date +%Y/%m/%d" "%H:%M:%S` #実行結果に記録する現在時刻を変数格納
 ping $line -c $counter -w $waittime > /dev/null 2>&1 #ping実行 #★2

 if [ $? = 0 ] ; then  #★3 pingが成功したなら
   result="OK"  #"OK"を$result
  else          #pingが失敗したなら
   result="NG"  #"NG"を$result
 fi
 echo "$DATESTR,$line,$result" >> $res_dir$clfilename   #現在時刻,宛先IPアドレス,実行結果をファイルにリダイレクト

 sleep 1 #1秒待つ

done  < $tool_dir$iplist  #★1 宛先IPアドレス一覧ファイル名を指定
#############################

#####自動削除処理############
  rm -rf $res_dir$delfilename          #指定した過去日付ファイルを消す
#############################
  • 転用する場合はパラメータ内の各変数をお好みの値に変更したうえでお使いください
  • テクニック解説するコードは「★+数値」で表記しています

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

らいし

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

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

mkdir /work/pingtool
mkdir /work/pingtool/result

②次の例を参考に宛先IPアドレス一覧ファイルを作成してください。

[root@centos7 pingtool]# cat /work/pingtool/iplist.txt 
192.168.0.20
127.0.0.1
192.168.0.99

プログラム実行結果

[root@centos7 pingtool]# ./pingtool.sh 
[root@centos7 pingtool]# cat result/20220217_ping_result.csv 
2022/02/17 12:04:03,192.168.0.20,OK
2022/02/17 12:04:04,127.0.0.1,OK
2022/02/17 12:04:05,192.168.0.99,NG
らいし

pingを実行した時刻やIPアドレス、そして実行結果(OK or NG)がcsvファイルに記録されていますね

重要テクニック解説

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

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

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

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

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

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


“while read 変数”を用いた目的は、読み込む外部ファイルには宛先IPアドレスを書くことによって、pingを実行したい宛先IPアドレスを容易に編集・管理するです。

本体プログラムの中に、運用によって可変する頻度が高いパラメータ(今回の場合、宛先IPアドレス)を直書きしちゃうのはダサすぎます。

②pingコマンドについて

 ping ”IPアドレス” -c ”実行回数” -w ”待ち時間” > /dev/null 2>&1 

pingコマンドの基本情報を解説します。

pingコマンドの書式

ping ”オプション” “通信先”

pingコマンドのオプション一覧

オプション意味
-4IPv4を使用する(pingコマンドのデフォルト)
-6IPv6を使用する(ping6コマンドのデフォルト)
-c 回数パケットを送る回数
-i 秒数個々の送信の後に待つ秒数(デフォルトは1秒)
-w 秒数状況を問わず、pingコマンドの実行を指定した秒数で終わらせる
-n数値出力のみを行う(IPアドレスからホスト名を検索しない)
-q開始と終了時の要約のみで他は表示しない(quiet)
-v詳細な出力を行う(verbose)

引用元:【 ping 】コマンド/【 ping6 】コマンド――通信相手にパケットを送って応答を調べる

意識すべきテクニック

私が伝えるテクニックは次の2つです(超基本的なことですが)

  1. コマンドのパラメータをシェルに組み込むときは、変数で定義すること
     →後から変更しやすいようにするためです。
  2. 標準出力を伴うコマンドは/dev/null 2>&1をつける
     →標準出力をせず、ごみ箱に捨てちゃう的な良く使う例のやつ。
     シェルスクリプト組むとき、標準出力を伴うやつは基本これを付けておいたほうが無難。
     メモリとかの節約になるらしい・・・

③「if [ $? = 0 ] 」について

 if [ $? = 0 ] ; then
 ###実行コマンドA###
 else          
   ###実行コマンドB###
 fi

$?は特殊関数の1つで、前回実行したコマンドの成功/失敗の結果が数値で代入されます特性を持ちます。

特殊変数一覧

変数名   概要
$0シェルスクリプトのファイル名
$1~$nシェル引数の値。$1は第1引数、$2は第2引数…。
$#シェル引数の数
$*全引数リスト。”$*”のようにダブルクオートで囲むと、”$1 $2 … $n”形式。
$@全引数リスト。”$@”のようにダブルクオートで囲むと、”$1″ “$2” … “$n”形式。
$$実行中のシェルのプロセスID。
$?最後に実行したコマンドのリターンコード(戻り値)。通常は成功していれば0
$-シェルの実行オプション(setコマンドや#!/bin/bash行に付けたオプション。
$!シェルが最後に実行したバックグラウンドプロセスのPID。

引用元:特殊変数 (引数などの特殊な変数)

$0の値が”0″であればpingが成功、0以外ならpingが失敗となります。

この$?関数は色んなコマンドの分岐に使えます。
例えば、ファイルをgrepコマンド(ファイル内容の抽出条件指定)とかでサーチして、ヒット(表示有り)したら分岐Aへ。ヒット無し(何も表示無し)なら分岐Bへ みたい使い方も非常に便利な変数です。

悩み人

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

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

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

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

idea


私は監視システムを保守していました。
時折、共通点のない複数の被監視ノード疎通不可を数秒間検知する事象が発生しており、監視ユーザを困らせていました。

原因特定を行うにあたって、サーバ側かネットワーク側の障害かを切り分けるため、簡易調査ツールとしてこのシェルスクリプトを作りました。

この監視システムは、

  • クローズネットワーク
  • RHEL
  • GUI無し

で構築しているシステムであり、EXpingのようなフリーソフトは使えないので手組にしました。

調査したいネットワークのIPアドレスをいくつか設定しておき、cronで定期実行しておきます。もし障害事象が発生し、

監視システム:複数監視ノード異常検知発生
本ツール:ping NG検知あり

であればサーバ(アプリ)は悪くなく、ネットワーク側が疑わしいのでは?
という発想。
ま、これやる前からネットワーク側のせいだろうと予想は付いていましたが念の為。

今回は以上です。今回のシェルスクリプトは実務で使えるシェルとしては入門レベルですのでお試しにどうぞ!