前書き
何か作業するときに、監視システム以外から ping で確認したりしますよね。
Windows だと ExPing 使ったり。
そんな感じのことをシェルスクリプトでやりたいな、と思ったので書いてみた。
スクリプト
alive-monitor.sh
#!/usr/bin/env bash
###############################################
# 2017-10-08 とりあえず作成(MAC用)
# 2017-10-22 出力ログファイルへ実行スクリプト名($0)を追加
# --> 異なる ping 対象を記載したスクリプトファイルを複数配置しておいても対応可能に
# OS 自動判別追加(動作確認済み:MAC, CentOS6)
# 2017-10-23 cygwin で動作するように修正(動作確認済み:MAC, CentOS6 & 7, cygwin)
# 2017-10-29 Ctrl + c での終了時に、ログディレクトリを表示
#
###############################################
# memo
# ・連想配列使ってるので bash 4 系必須
# ・動作概要
# - 2秒でタイムアウトする ping を打って、tmp_xx.xx.xx.xx.txt ファイルへ記載する(毎回上書き)
# - ping 実行する関数は & を付けて実行することにより、連想配列の ping 対象に一気に実行をかける
# - sleep で、ping の実行間隔を調整しつつ、ping の結果が txt へ記載されるのを待つ
# - sleep 後、ping の実行結果(tmp_xx.xx.xx.xx.txt)を全て cat で閲覧
# - というわけで、ping の -W と sleep の時間に注意が必要
# - Ctrl + c で終了させる
function usage_exit() {
cat <<_EOT_
Usage:
$0 [-h] [-d] [-l]
Description:
定期定期に対象へ ping を打ってモニタリングする
Options:
-d debug mode ON (未使用)
-l log OFF
-h help
_EOT_
exit 1
}
# If there are 0 arguments --> error
# if [ $# = 0 ]; then
# usage_exit
# exit 1
# fi
# フラグの初期値設定
FLAG_DEBUG=off
FLAG_LOG=on
# 引数処理
if [ "$OPTIND" = 1 ]; then
while getopts dhl OPT
do
case $OPT in
d)
FLAG_DEBUG="on"
echo ">>> debug mode ON <<<"
;;
l)
FLAG_LOG="off"
echo ">>> log OFF <<<"
;;
h)
usage_exit
;;
\?)
usage_exit
;;
esac
done
else
echo "No installed getopts-command." 1>&2
exit 1
fi
shift $((OPTIND - 1))
######################################
# 文字コード変換関数 for cygwin
function wincmd() {
CMD=$1
shift
$CMD $* 2>&1 | iconv -f cp932 -t utf-8
}
######################################
function exec_ping(){
ip=${1}
name=${2}
OS_type=${3}
script_name=${4}
outut_file_name=tmp_${script_name}_${ip}.log
# OS の種類で ping のオプション、awk で引っ掛ける&表示する文字列を調整
if [ "$OS_type" = "mac" ]; then
# MAC の場合 -w の単位は msec
result=`ping -c 1 -W 2000 ${ip} | awk '/ttl/{print $6 " " $7}'`
elif [ "$OS_type" = "cygwin" ]; then
result=`${PING} -n 1 -w 2000 ${ip} | awk '/TTL/{print $5 $6 " " $7}'`
elif [ "$OS_type" = "linux" ]; then
result=`ping -c 1 -w 2 ${ip} | awk '/ttl/{print $6 " " $7}'`
else
echo ">>> Error : OS が判別できないため ping が実行できませんでした"
exit
fi
if [ "${result}" != "" ]; then
echo `date +%Y-%m-%d_%H:%M:%S` ": ${ip} ${name} ${result}" > ${OUTPUT_DIR}/${outut_file_name}
else
echo `date +%Y-%m-%d_%H:%M:%S` ": ${ip} ${name} NG!!" > ${OUTPUT_DIR}/${outut_file_name}
fi
}
######################################
# OS 判定
# 本当は、OS の種別ではなく ping の種類の判別が一番正しいんだろうけど。。。
#OS_type=`uname | egrep -i "darwin|cygwin|linux"`
#echo ">>> OS type (uname) : ${OS_type}"
#if [ ${OS_type} = "" ]; then
# echo ">>> Your platform (`uname`) is not supported!! :p"
# exit
#fi
if [ `uname | grep -i cygwin` ]; then
OS_type='cygwin'
elif [ `uname | grep -i darwin` ]; then
OS_type='mac'
elif [ `uname | grep -i linux` ]; then
OS_type='linux'
else
echo ">>> Your platform (`uname`) is not supported!! :p"
exit 1
fi
echo ">>> OS type : ${OS_type}"
# 実行スクリプト名取得(出力ログファイルで利用)
# script_name=`echo $0 | sed -e "s/^\.\///g" -e "s/\.sh$//g"`
# cygwin は $0 が full path になっていたので修正(メモとして上記を残す)
script_name=`echo $0 | awk -F'/' '{print $NF}' | sed -e "s/\.sh$//g"`
# 出力ディレクトリ
OUTPUT_DIR="/tmp/alive-monnitor"
EXEC_TIME=`date +%Y%m%d_%H%M%S`
# cygwin 用 実行 ping コマンド
PING='wincmd /cygdrive/c/Windows/System32/PING.exe'
# ping 実行間隔(秒数)
INTERVAL=5
# モニタリング対象の連想配列
declare -A ips
ips["8.8.8.8"]="GoogleDNS01"
ips["8.8.4.4"]="GoogleDNS02"
# ログ出力ディレクトリ作成
if [ ! -d ${OUTPUT_DIR} ]; then
mkdir -p ${OUTPUT_DIR}
else
# すでにディレクトリが存在していた場合は、不要ファイル(tmp_${script_name}_*)を削除
rm ${OUTPUT_DIR}/tmp_${script_name}_* > /dev/null 2>&1
fi
echo ">>> log directory : ${OUTPUT_DIR}/"
echo " ----- "
trap '
echo ""
echo ""
echo ">>> log directory : ${OUTPUT_DIR}/"
exit 0
' 2
# Ctrl + c で終了させられるまで無限ループ
while : ; do
# 連想配列でループ処理
for ip in ${!ips[@]}; do
name=${ips[${ip}]}
exec_ping ${ip} ${name} ${OS_type} ${script_name} &
done
# ping 実行間隔調整用 sleep
sleep ${INTERVAL}
# $FLAG_LOG が ON の場合は、tee で標準出力とファイル両方へ出力。OFF の場合は標準出力のみ
if [ "$FLAG_LOG" = "on" ]; then
cat ${OUTPUT_DIR}/tmp_${script_name}_* | column -t | tee -a ${OUTPUT_DIR}/result_${script_name}_${EXEC_TIME}.log
echo " ----- " | tee -a ${OUTPUT_DIR}/result_${script_name}_${EXEC_TIME}.log
else
cat ${OUTPUT_DIR}/tmp_${script_name}_* | column -t
echo " ----- "
fi
chmod 666 ${OUTPUT_DIR}/*
done
実行例
$ ./alive-monitor.sh
>>> OS type : mac
>>> log directory : /tmp/alive-monnitor/
-----
2017-10-29_19:50:06 : 8.8.4.4 GoogleDNS02 ttl=53 time=50.349
2017-10-29_19:50:06 : 8.8.8.8 GoogleDNS01 ttl=53 time=61.549
-----
2017-10-29_19:50:11 : 8.8.4.4 GoogleDNS02 ttl=53 time=52.303
2017-10-29_19:50:11 : 8.8.8.8 GoogleDNS01 ttl=53 time=42.530
-----
^C
>>> log directory : /tmp/alive-monnitor/
$
$ ls -1 /tmp/alive-monnitor/
result_alive-monitor_20171029_194604.log
result_alive-monitor_20171029_194743.log
result_alive-monitor_20171029_194858.log
result_alive-monitor_20171029_195006.log
tmp_alive-monitor_8.8.4.4.log
tmp_alive-monitor_8.8.8.8.log
$