LogicDaemon

check_and_reroute_default.cmd

Aug 22nd, 2013
520
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. @REM coding:OEM
  2. @ECHO OFF
  3.  
  4. REM здесь надо указать путь к файлу журнала. Можно относительный, можно абсолютный.
  5. SET log="d:\var\logs\%~n0\%~n0.log"
  6. REM Журнал надо периодически чистить, делать logrotate то есть. Или можно просто удалять файл.
  7.  
  8. REM цель только по IP (213.180.204.3), по hostname (ya.ru) нельзя, потому что:
  9. REM     1. связи с DNS может не быть, и соответственно имя в IP не разрешится
  10. REM     2. route add работает только с IP
  11. REM здесь указан первый IP OpenDNS
  12. SET target=208.67.222.222
  13.  
  14. rem Если не надо возвращаться с резервного канала при восстановлении основного,
  15. rem раскомментируйте следующую строчку. В этом случае меньше будет манипуляций с таблицей маршрутов.
  16. rem PING %target% -n 1 >>%log% 2>&1 && EXIT /B
  17.  
  18. REM --- настройка закончена, дальше трогать ничего не надо ---
  19. REM последний использованный шлюз записан в currentgw.txt. Если файла нет, будет создан.
  20. FOR /F "usebackq delims=" %%I IN ("currentgw.txt") DO SET currentgw=%%I
  21. ECHO.
  22. ECHO currentgw.txt:     %currentgw%|tee -a %log%
  23.  
  24. CALL :ReadRoute currentgw 0.0.0.0
  25. ECHO Current default route: %currentgw%|tee -a %log%
  26.  
  27. REM Кроме, может быть, последней функции, где разбирается вывод ping-а.
  28. SET foundgw=
  29.  
  30. REM небольшая вставка для мониторинга хостов
  31. IF EXIST "IPs_to_monitor.list" CALL :CheckHost %currentgw% && CALL :HostsMonitoring
  32.  
  33. REM из файла gateways.list читаются IP адреса шлюзов (1 строка - 1 IP)
  34. REM начало цикла перебора шлюзов
  35. FOR /F "usebackq delims=" %%I IN ("gateways.list") DO (
  36.     CALL :CheckGateway %%I && EXIT /B
  37. )
  38.  
  39. REM собственно, если выполнение дошло сюда, значит ни через один из шлюзов цель недоступна.
  40. REM Либо настал конец Интернета, либо надо выбирать более лучше отличающихся провайдеров,
  41. REM либо просто умерла цель. Можно было бы сообщить что-н типа
  42. REM net send * Интернет кончился! Мы все умрём!
  43. REM Но я не буду.
  44. ECHO %DATE% %TIME% No working gateways found!
  45.  
  46. EXIT /B
  47.  
  48. :CheckGateway
  49.     ECHO %DATE% %TIME% checking gateway %1|tee -a %log%
  50.     REM проверяется связь со шлюзом
  51.     ping %1 -n 1
  52. rem     >>%log% 2>&1
  53.     REM Пинги сначала идут через стандартный маршрут,
  54.     REM поэтому пигновать что-либо за любым из роутеров бесполезно
  55.    
  56.     REM если шлюз не отвечает, продолжать нет смысла
  57.     IF ERRORLEVEL 1 EXIT /B
  58.    
  59.     REM Шлюз отвечает, надо проверить, доступна ли через него цель (target)
  60.     REM добавляется маршрут для цели, но только если текущий шлюз не тот же, что и проверяемый
  61.     REM MASK 255.255.255.255 по умолчанию
  62.     ROUTE DELETE %target% 2>&1
  63.     ping 127.0.0.1 -n 2 >NUL
  64.    
  65.     ECHO Adding temporary route to %target% through %1|tee -a %log%
  66.     IF "%currentgw%"=="%1" GOTO :SkipAddingTempRoute
  67.     ROUTE ADD %target% %1 METRIC 1 2>&1 |tee -a %log%
  68.     CALL :CheckRoute %target% %1 || EXIT /B 1
  69.  
  70.     REM если не подождать, Windows не успевает обновить таблицу маршрутов,
  71.     REM и даже удаление перед закрывающей строчкой не удаётся с сообщением,
  72.     REM что удалять нечего и маршрута нет.
  73.     REM Но маршрут внезапно обнаруживается к следующему шагу цикла
  74.     REM и не позволяет использовать следующий шлюз.
  75.     ping 127.0.0.1 -n 2 >NUL
  76. :SkipAddingTempRoute
  77.  
  78.     ECHO Checking %target% availability|tee -a %log%
  79.     REM проверка, и если ошибки нет, запись найденного работающего шлюза
  80.     CALL :CheckHost %target% && SET foundgw=%1
  81.  
  82.     IF NOT "%currentgw%"=="%foundgw%" (
  83.     ECHO Removing temporary route to %target%|tee -a %log%
  84.     REM удаление временного маршрута.
  85.     ROUTE DELETE %target% 2>&1 |tee -a %log%
  86.     ping 127.0.0.1 -n 2 >NUL
  87.     CALL :CheckRoute %target% %1 && ECHO Temporary route not removed!!!|tee -a %log%
  88.     )
  89.     ECHO Current gateway: "%currentgw%"     Working gateway: "%foundgw%"|tee -a %log%
  90.  
  91.     REM foundgw устанавливается только если найден шлюз, через который доступна цель
  92.     REM но если он совпадает с тем, что используется сейчас, менять ничего не надо
  93.     IF "%currentgw%"=="%foundgw%" EXIT /B 0
  94.     IF NOT "%foundgw%"=="" GOTO :SwitchGateway
  95.  
  96.     REM конец цикла перебора шлюзов
  97. EXIT /B 1
  98.  
  99. :SwitchGateway
  100.     ECHO %DATE% %TIME% Switching route to %foundgw%|tee -a %log%
  101.     REM Удаление старого маршрута
  102.     ECHO Removing default route|tee -a %log%
  103.     ROUTE DELETE 0.0.0.0 2>&1 |tee -a %log%
  104.     ping 127.0.0.1 -n 2 >NUL
  105.     CALL :CheckRoute 0.0.0.0 && ECHO Default route not removed!|tee -a %log%
  106.     REM Добавление нового
  107.     ECHO Adding default route through %foundgw%|tee -a %log%
  108.     ROUTE ADD 0.0.0.0 MASK 0.0.0.0 %foundgw% METRIC 50 2>&1 |tee -a %log%
  109.     CALL :CheckRoute 0.0.0.0 %foundgw% || ECHO New default route not added!|tee -a %log%
  110.     REM и запись нового в файл
  111.     ECHO %foundgw%>currentgw.txt
  112. EXIT /B 0
  113.  
  114. :ReadRoute
  115.     rem Читает первый шлюз для %2 в переменную %1
  116.     FOR /F "usebackq tokens=1,3" %%I IN (`route print^|FIND " %~2 "`) DO IF "%%I"=="%~2" (
  117.     SET %~1=%%J
  118.     EXIT /B 0
  119.     )
  120. EXIT /B 1
  121. :CheckRoute
  122.     rem Проверка, что в существует маршрут до %1 через %2
  123.     rem ROUTE ADD не возвращает код ошибки, даже если маршрут добавить не удалось
  124.     rem поэтому надо проверять, насколько удачно он добавился
  125.     FOR /F "usebackq tokens=1,3" %%I IN (`route print^|FIND " %~1 "`) DO IF "%%I"=="%~1" (
  126.     IF "%~2"=="" EXIT /B 0
  127.     IF "%%J"=="%~2" EXIT /B 0
  128.     )
  129. EXIT /B 1
  130.  
  131. rem Пинг сволочь, ибо возвращает 0 даже если ему ответили no route to host
  132. rem Наример:
  133. rem c:\Scripts>PING 208.67.222.222 -n 1
  134. rem Pinging 208.67.222.222 with 32 bytes of data:
  135. rem Reply from 193.46.213.10: Destination host unreachable.
  136. rem Ping statistics for 208.67.222.222:
  137. rem     Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
  138. rem Approximate round trip times in milli-seconds:
  139. rem     Minimum = 0ms, Maximum = 0ms, Average = 0ms
  140. rem После этого errorlevel 0, видимо, потому что Lost = 0. Но связи-то нет!
  141.  
  142. rem поэтому нужна следующая функция:
  143. :CheckHost
  144. rem FOR используется для разбора того, что пишет ping, поскольку код ошибки неадекватен.
  145. rem skip=3 значит, что из ответа надо пропустить первые 3 строки:
  146. rem     пустая, обмен данными с ..., и ещё пустая.
  147. rem Если у Вас ответ PING выглядит по другому, эту часть надо исправлять.
  148. rem Например, в Vista skip=2
  149.     FOR /F "usebackq delims==: skip=3 tokens=1,2*" %%J IN (`PING %1 -n 1`) DO (
  150.     ECHO Pinging %1: %%J: %%K=%%L >>%log%
  151. rem     Ping %1 -n 1 -r 4 >>%log% 2>&1
  152. rem Следующая строка для русской версии Windows. Если у Вас английская, её можно закомментировать.
  153.     IF NOT ERRORLEVEL 1 IF "%%~J"=="Ответ от %1" IF "%%~K"==" число байт" EXIT /B
  154. rem Если у Вас русская версия Windows, можно закомментировать следующую строчку.
  155.     IF NOT ERRORLEVEL 1 IF "%%~J"=="Reply from %1" IF "%%~K"==" bytes" EXIT /B
  156. rem Возможно, у Вас ping будет отвечать, используя другие слова.
  157. rem В этом случае во второй IF вместо Reply from надо написать то, что написано до IP,
  158. rem а в 3й, вместо " bytes", то, что написано между двоеточием : и знаком равенства =,
  159. rem включая пробелы.
  160.  
  161. rem Если первая строчка ответа PING не соответствует нормальному ответу можно выходить,
  162. rem Ибо сводка неинтересна.
  163.     EXIT /B 1
  164.     )
  165. rem Если выполнение дошло до сюда, значит PING ответил меньше skip= строк.
  166. rem Это явно что-то ненормальное, так что стоит записать в лог.
  167.     ECHO Last ping reply contains less than 3 lines>>%log%
  168.     ping %1 -n 1 >>%log% 2>&1
  169. EXIT /B 1
  170.  
  171. :HostsMonitoring
  172. ECHO Hosts monitoring...|tee -a %log%
  173. FOR /F "usebackq tokens=1* delims=:" %%I IN ("IPs_to_monitor.list") DO (
  174.     CALL :CheckHost %%J && ECHO     %%I %%J     ok
  175.     IF ERRORLEVEL 1 (
  176.     ECHO Error pinging %%I: %DATE% %TIME% %%J|tee -a "d:\var\logs\link-monitoring\%%~I %%~J.log"
  177.     IF NOT EXIST "d:\var\logs\link-monitoring\pathping %%~I %%~J %DATE%.log" START "" %comspec% /C pathping %%~J ^>"d:\var\logs\link-monitoring\pathping %%~I %%~J %DATE%.log" 2^>^&1
  178.     ECHO    %%I %%J     failure
  179.     )
  180. )
  181. EXIT /B
RAW Paste Data