/usr/local/etc/ping_hosts
192.168.147.1 192.168.147.2 192.168.147.3 192.168.147.4 192.168.147.5 192.168.147.6 192.168.147.7 192.168.147.8 192.168.147.9 192.168.147.10
util_common.bash
# # 共通関数群(bash 用) # # BSD スタイルの ps コマンド # 引数: ps コマンドの引数と同じ ucb_ps () { local CMD_PS=/usr/ucb/ps if [ ! -x ${CMD_PS} ]; then CMD_PS=ps fi ${CMD_PS} "$@" } # ロケール(言語)設定をデフォルト(POSIX)にする # 引数: なし unset_linguas () { export LC_ALL=C export LC_MESSAGES=C export LANGUAGE=C export LANG=C } # 一時ディレクトリの作成 # 引数: 一時ディレクトリの親ディレクトリ # (省略時デフォルト: ${TMP_ROOT}) # 出力: 作成したディレクトリ名 # 終了ステータス: 0: 成功, 1: 失敗 # シェル変数: # TMP_ROOT(IN): 一時ディレクトリの親ディレクトリ # (省略時デフォルト: ${HOME}) make_tmp_dir () { # 一時ディレクトリの親ディレクトリ local TMP_ROOT="${1:-${TMP_ROOT:-${HOME}}}" local tmpdir=$(basename "$0")$$ tmpdir="${TMP_ROOT}/${tmpdir}" mkdir "${tmpdir}" > /dev/null 2>&1 if [ $? -eq 0 ] ; then echo "${tmpdir}" chmod 700 "${tmpdir}" else echo "Can't create directory: ${tmpdir}" 1>&2 return 1 fi } # 一時ディレクトリの削除 # 引数: 一時ディレクトリの親ディレクトリ # (省略時デフォルト: ${TMP_ROOT}) # 出力: なし # 終了ステータス: 0: 成功, 1以上: 失敗 # TMP_ROOT(IN): 一時ディレクトリの親ディレクトリ # (省略時デフォルト: ${HOME}) clean_tmp_dir () { # 一時ディレクトリの親ディレクトリ local TMP_ROOT="${1:-${TMP_ROOT:-${HOME}}}" local tmpdir=$(basename "$0")$$ tmpdir="${TMP_ROOT}/${tmpdir}" # ディレクトリが存在しなければエラーにします if [ ! -d "${tmpdir}" ]; then echo "No such directory: ${tmpdir}" 1>&2 return 1 fi # 対象がシンボリックの場合は、想定外のためエラーにします if [ -L "${tmpdir}" ]; then echo "Can't delete unexpected symlink: ${tmpdir}" 1>&2 return 1 fi # rm コマンドの終了ステータスをそのまま返します rm -rf "${tmpdir}" > /dev/null 2>&1 }
ping.bash
#!/bin/bash # usage: ping.bash # 監視対象ホストを記述したファイル # (書式は 1 行に 1 ホスト) PING_HOSTS="/usr/local/etc/ping_hosts" # 汎用pingコマンドインターフェース # 使い方: # ping_common[ ] # 引数: # hostname: ホスト名/IPアドレス # timeout: pingのタイムアウト(秒) # 出力: # なし(エラー出力はあり) # 終了ステータス: # 0: 応答あり # 1: 応答なし # 2以上: エラー ping_alive_common () { # システム(unameの結果)ごとに処理を分岐 case $(uname -s) in Linux | NetBSD | OpenBSD) ping_alive_bsd $1 $2 status=$? ;; SunOS) ping_alive_solaris $1 $2 status=$? ;; FreeBSD) ping_alive_freebsd $1 $2 status=$? ;; *) # 上記以外のシステムでは、自分で調べて修正してください echo "This system is not supported." 1>&2 return 2 ;; esac return ${status} } # Linux/NetBSD/OpenBSD用pingコマンドインタフェース # 使い方: # ping_alive_bsd [ ] # 引数: # hostname: ホスト名/IPアドレス # timeout: pingのタイムアウト(秒) # 出力: # なし(エラー出力はあり) # 終了ステータス: # 0: 応答あり # 1: 応答なし(またはエラー) # 2以上: エラー ping_alive_bsd () { local timeout=${2:+"-w $2"} local status ping -c 1 ${timeout} $1 > /dev/null status=$? # 不正な引数の場合は終了ステータスは2以上(?) if [ $status -ge 2 ]; then # timeout オプションを削除して再試行 ping -c 1 $1 > /dev/null status=$? fi return ${status} } # FreeBSD用pingコマンドインタフェース # 使い方: # ping_alive_freebsd [ ] # 引数: # hostname: ホスト名/IPアドレス # timeout: pingのタイムアウト(秒) # 出力: # なし(エラー出力はあり) # 終了ステータス: # 0: 応答あり # 1: 応答なし # 3以上: エラー ping_alive_freebsd () { local timeout=${2:+"-t $2"} ping -c 1 ${timeout} $1 > /dev/null status=$? # 不正な引数の場合 = 古い実装は終了ステータスが2以上 if [ $? -ge 2 -a "${timeout}" != "" ]; then # timeout オプションを削除して再試行 ping -c 1 $1 > /dev/null status=$? fi case ${status} in 0) return 0 ;; 1 | 2) return 1 ;; *) return ${status} ;; esac } # Solaris(SunOS)用pingコマンドインタフェース # 使い方: # ping_alive_solaris [ ] # 引数: # hostname: ホスト名/IPアドレス # timeout: pingのタイムアウト(秒) # 出力: # なし(エラー出力はあり) # 終了ステータス: # 0: 応答あり # 1: 応答なし # 2以上: エラー ping_alive_solaris () { ping $1 $2 > /dev/null } # 非同期 ping 実行 # 使い方: # ping_async [ ] [ ] # 引数: # hostname: ホスト名/IPアドレス # directory: ログ出力先ディレクトリ(デフォルトはカレントディレクトリ) # timeout: ping タイムアウト(秒) # 出力: # なし # 終了ステータス: # 0: pingの実行に成功 # 1以上: エラー ping_async () { local hostname=$1 local resultfile="${2:+${2}/}${hostname}" local timeout=$3 rm -f ${resultfile} > /dev/null 2>&1 ( ping_alive_common ${hostname} ${timeout} \ > /dev/null 2> "${resultfile}" echo $? >> "${resultfile}" ) > /dev/null 2>&1 & } # 非同期 ping 実行結果取得 # 使い方: # ping_check_result [ ] # 引数: # hostname: ホスト名/IPアドレス # directory: ログ出力先ディレクトリ(デフォルトはカレントディレクトリ) # 出力: # なし # 終了ステータス: # 0: 応答あり # 1: 応答なし # 2以上: エラー # 70: 結果不明(結果ファイルが存在しない/読み込めない) ping_check_result () { local hostname=$1 local resultfile="${2:+${2}/}${hostname}" local num_line local status [ -r "${resultfile}" ] || return 70 status=$(tail -1 "${resultfile}") # エラーの表示 if [ ${status} -ge 2 ]; then num_line=$(wc -l "${resultfile}" | awk '{print $1}') if [ ${num_line} -gt 1 ]; then sed ${num_line}d "${resultfile}" 1>&2 fi fi return ${status} } # 複数ホストへのping同時実行 # 使い方: # ping_from_file [ ] [ ] # 引数: # hostname: ホスト名/IPアドレス # directory: ログ出力先ディレクトリ(デフォルトはカレントディレクトリ) # timeout: ping タイムアウト(秒) # 出力: # <ホスト名>: <ステータス> # ... # # ステータスは 0:応答あり 1:応答なし 2以上:エラー # 終了ステータス: # 常に 0 ping_from_file () { local inputfile="$1" local hostname local dummy # 入力ファイルの読み込みチェック if [ ! -r "${inputfile}" ]; then echo "No such file/Can't read file: ${inputfile}" 1>&2 return 1 fi # 位置パラメータを以下のようにする # $1: result_dir(省略可), $2: timeout(省略可) shift # 第2要素以降は無視する。すなわち # 192.168.1.1 # ルーター # のような記述も OK である while read hostname dummy; do # 空行/コメント行は無視 case "${hostname}" in "") continue ;; "#"*) continue ;; esac ping_async ${hostname} "$@" > /dev/null done < "${inputfile}" # ping_async で実行した非同期コマンドの終了を待つ wait # 位置パラメータを以下のようにする # $1: result_dir(省略可) if [ $# -ge 2 ]; then set -- "$1" fi while read hostname dummy; do # 空行/コメント行は無視 case "${hostname}" in "") continue ;; "#"*) continue ;; esac ping_check_result ${hostname} "$@" echo "${hostname}: $?" done < "${inputfile}" return 0 } # メイン処理 # util_common.bash を読み込む(make_tmp_dir/clean_tmp_dir) FILE_UTIL=util_common.bash . "${FILE_UTIL}" 2> /dev/null \ || . "${0%/*}/${FILE_UTIL}" 2> /dev/null if [ $? -ne 0 ]; then echo "Can't load ${FILE_UTIL}!" 1>&2 exit 1 fi # 作業ディレクトリの作成 tmpdir=$(make_tmp_dir 2>/dev/null) if [ $? -ne 0 ]; then echo "Can't create temporary directory!" 1>&2 exit 2 fi # trap の設定 SIGNALS="HUP INT QUIT PIPE TERM" trap "{ clean_tmp_dir; exit; }" ${SIGNALS} # ping 監視の実行 ping_from_file "${PING_HOSTS}" "${tmpdir}" # 作業ディレクトリの削除と trap 解除 clean_tmp_dir trap ${SIGNALS}
0 件のコメント:
コメントを投稿