--[[ ●ping 応答監視スクリプト   指定したアドレスに宛に ping を実行してその応答を監視し、応答がなかった場合   に管理者にメールを送信して知らせるスクリプトです。ping を実行する宛先IPアド   レスは複数指定することができます。   指定した回数連続して ping に対する応答がなかった場合には、管理者にメールを   送信して知らせます。その後、指定した回数連続して応答があった場合には、応答   が回復したと判断します。設定値 down_mail を true に設定している場合には、応   答が回復した際にもメールを送信します。 <説明> ・このファイルを RTFS か外部メモリに保存してください。 ・本項目の config の設定では schedule at コマンドでルーター起動時に Lua スク リプトが実行されるように設定しています。 ・スクリプトを停止するときは terminate lua コマンドを実行してください。 ・再度、Lua スクリプトを実行する場合は lua コマンドで実行してください。 ・★マークの付いた設定値は変更が可能です。 <ノート>  ・メールの送信失敗時に出力する SYSLOG レベルを指定可能です。   SYSLOG のレベルを指定するには、log_level を設定してください。   debug レベル、notice レベルの SYSLOG を出力するためには、それぞれ以下の設定   が必要です。    debug レベル ・・・ syslog debug on    notice レベル・・・ syslog notice on  ・本スクリプトファイルを編集する場合、文字コードは必ず Shift-JIS を使用してく   ださい。 ]] --------------------------## 設定値 ##-------------------------------- -- 監視間隔(1 - 864000 秒) idle_time = (監視間隔) -- ★ -- ping を実行する宛先 IP アドレス dst_tbl = { -- ★ "(宛先 IP アドレス1)", "(宛先 IP アドレス2)" } -- ping への応答がない、または応答が回復したと判断する連続回数(1, 2 ..) count = (回数) -- ★ -- 応答が回復したときにもメールを送るかどうか(送る: true / 送らない: false) down_mail = (true / false) -- ★ -- メールの設定 mail_tbl = { -- ★ smtp_address = "(SMTP サーバのアドレス)", from = "(送信元メールアドレス)", to = "(宛先メールアドレス)" } -- メールの送信に失敗したときに出力する SYSLOG のレベル(info, debug, notice) log_level = "(SYSLOG レベル)" -- ★ ----------------------## 設定値ここまで ##---------------------------- ------------------------------------------------------------ -- ping を実行し、到達したかどうかを返す関数 -- ------------------------------------------------------------ function ping_reach(adr) local rtn, str, loss local reach = false local cmd = "ping " .. adr local ptn = "(%d+)%.%d+%%" rtn, str = rt.command(cmd) if (rtn) and (str) then loss = str:match(ptn) if (loss) then loss = tonumber(loss) if (loss == 0) then reach = true end end end return rtn, reach, str end -------------------------------------------------------------- -- 連続何回 ping に応答がないかを示すカウンターの処理関数 -- -------------------------------------------------------------- function count_proc(t, reach, th) local rtn = 0 if (not reach) then if (not t.flag) then t.ng = t.ng + 1 if (t.ng == th) then rtn = 1 t.flag = true end else if (t.ok > 0) then t.ok = 0 end end else if (t.flag) then t.ok = t.ok + 1 if (t.ok == th) then rtn = -1 t.flag = false t.ng = 0 t.ok = 0 end else if (t.ng > 0) then t.ng = 0 end end end return rtn end ------------------------------------------------------------ -- メール本文を作成する関数 -- ------------------------------------------------------------ function make_pingmsg(tbl, reach, adr, cnt, sec, down) local rtn local str = "" rtn = count_proc(tbl, reach, cnt) if (rtn < 0) then if (down) then str = "pingの応答が回復しました。\r\n" str = str .. string.format(" 送信先: %s\r\n 監視間隔: %d(秒)\r\n\r\n",adr, sec) end elseif (rtn > 0) then str = "pingの応答がありません。\r\n" str = str .. string.format(" 送信先: %s\r\n 応答がなかった回数: %d回\r\n 監視間隔: %d(秒)\r\n\r\n", adr, cnt, sec) end return str end ------------------------------------------------------------ -- 連続不応答回数を記録するテーブルの初期化関数 -- ------------------------------------------------------------ function init_count_tbl(n, cnt_t) for i = 1, n do cnt_t[i] = {ng = 0, ok = 0, flag = false} end end ------------------------------------------------------------ -- 現在の日時を取得する関数 -- ------------------------------------------------------------ function time_stamp() local t t = os.date("*t") return string.format("%d/%02d/%02d %02d:%02d:%02d", t.year, t.month, t.day, t.hour, t.min, t.sec) end ------------------------------------------------------------ -- メインルーチン -- ------------------------------------------------------------ local rtn, reach, str, adr local cnt_tbl = {} init_count_tbl(#dst_tbl, cnt_tbl) while (true) do mail_tbl.text = "" for i, adr in ipairs(dst_tbl) do rtn, reach, str = ping_reach(adr) if (rtn) then mail_tbl.text = mail_tbl.text .. make_pingmsg(cnt_tbl[i], reach, adr, count, idle_time, down_mail) else mail_tbl.text = string.format("%s (ping送信先: %s\r\n\r\n)", str, dst_tbl[i]) end end if (mail_tbl.text:len() > 0) then mail_tbl.subject = string.format("watch ping : multi destination (%s)", time_stamp()) rtn = rt.mail(mail_tbl) if (not rtn) then rt.syslog(log_level, "failed to send mail. (Lua スクリプトファイル名)") end end rt.sleep(idle_time) end