Скрипт для проверки ширины канала

Здесь выкладываем скрипты
Правила форума
Уважаемые Пользователи форума, обратите внимание!
Ни при каких обстоятельствах, Администрация форума, не несёт ответственности за какой-либо, прямой или косвенный, ущерб причиненный в результате использования материалов, взятых на этом Сайте или на любом другом сайте, на который имеется гиперссылка с данного Сайта. Возникновение неисправностей, потерю программ или данных в Ваших устройствах, даже если Администрация будет явно поставлена в известность о возможности такого ущерба.
Просим Вас быть предельно осторожными и внимательными, в использовании материалов раздела. Учитывать не только Ваши пожелания, но и границы возможностей вашего оборудования.
Ответить
druide
Сообщения: 5
Зарегистрирован: 02 окт 2014, 06:10

Добрый день!
Стояла задача мониторинга ширины канала между головным офисом и филиалами предприятия. Везде используются роутеры микротик, поэтому решил использовать встроенный тест скорости.
Вот что получилось. Код хорошо комментирован, поэтому переделать его "под себя" думаю будет не сложно.

Код: Выделить всё

# Скрипт проверяет ширину канала между текущим и заданными хостами и отправляет результат на почту
# Скорость приема и передачи, соответственно
:local RxSpeed 0
:local TxSpeed 0
# Тело письма отчета
:local Msg ""
# Тема письма
:local Subject ""
# Текущее время и дата
:local CurDate ([/system clock get date]." ".[/system clock get time])
# Тут список ip хостов которые тестируем (это можно убрать, если будет тестироваться только один ip)
:local IpList [:toarray x.x.x.x,x.x.x.x]
# Описание хостов (что-бы отчет выглядел более понятным)
:local IpDescriptions [:toarray "host1, host2"]

:set Subject ("Band Width report ".$CurDate)
:local i 0
# Перебираем адреса в массиве IpList
:foreach TestIP in=$IpList do={
# Собственно сам тест
# Тут, user и password - учетные данные пользователя на удаленном устройстве, имеющего права на данную операцию.
/tool bandwidth-test address=$TestIP duration=60s protocol=tcp user=user password=password direction=both do={:set RxSpeed [$"rx-total-average"];:set TxSpeed [$"tx-total-average"]}

:set RxSpeed ($RxSpeed/1024)
:set TxSpeed ($TxSpeed/1024)
# Формируем отчет
:set Msg ($Msg.("Speed test to ".[:pick $IpDescriptions $i]."\r\nDestination ip:".$TestIP."\r\nRxSpeed= ".$RxSpeed." Kb/s\r\n"."TxSpeed= ".$TxSpeed." Kb/s\r\n\r\n"))

:set i ($i+1)
}
# Отправляем письмо.
# server - ip почтового сервера
# from - почтовый ящик с которого будет оправляться отчет
# user, password - данные авторизации на почтовом сервере.
# to - куда отправляем отчет
/tool e-mail send server=x.x.x.x port=25 from=router@server.ru body=$Msg user=user password=password to=admin@server.ru subject=$Subject

Спасибо участникам форума, кто помог в написании скрипта.


Аватара пользователя
drpioneer
Сообщения: 142
Зарегистрирован: 30 май 2013, 10:20

Приветствую.

Вариант этого же скрипта с выводом инфы в журнал.

Код: Выделить всё


# Script for determining the bandwidth of VPN interfaces by Druide
# https://forummikrotik.ru/viewtopic.php?t=5986
# tested on ROS 6.46.5
# updated 2020/05/10

:local listIP [:toarray 192.168.89.1,192.168.90.1,192.168.91.1];
:local descriptionsIP [:toarray Moscow,Bryansk,Pupkino];
:local currentDate ([/system clock get date]." ".[/system clock get time]);
:local rxSpeed 0;
:local txSpeed 0;
:local index 0;
:local message "";
:local subject "";
:set subject (">>>        Bandwidth VPN report on ".$currentDate);
:foreach testIP in=$listIP do={
    :do {
        /tool bandwidth-test address=$testIP duration=60s protocol=tcp user=LOGIN password=PASSWORD direction=both do={ :set rxSpeed [$"rx-total-average"]; :set txSpeed [$"tx-total-average"]; }
        :set rxSpeed ($rxSpeed/1024);
        :set txSpeed ($txSpeed/1024);
        :set message ($message.(">>> speed test to ".[:pick $descriptionsIP $index].", destination IP: ".$testIP."\r\n>>> speed Rx: ".$rxSpeed." Kbps".", Tx: ".$txSpeed." Kbps\r\n"));
        :set index ($index+1);
    } on-error={ :log warning (">>> Script error. Not found VPN IP"); }
}
:log warning ($subject);
:log warning ($message);

Последний раз редактировалось drpioneer 20 фев 2021, 08:48, всего редактировалось 1 раз.


Аватара пользователя
drpioneer
Сообщения: 142
Зарегистрирован: 30 май 2013, 10:20

Добрый день.

Обновил скрипт на предмет автоматического поиска и перебора подходящих VPN-интерфейсов.

Код: Выделить всё


# Script for determining the bandwidth of VPN interfaces by drPioneer
# https://forummikrotik.ru/viewtopic.php?t=5986
# tested on ROS 6.48
# updated 2021/04/21

:do {   
    :local  localUser       "login";
    :local  localPassword   "password";
    :local  nameVPN         "VPN";
    :local  fileName        "disk1/bandwidth.txt";
    :local  countPing       2;
    :local  rxSpeed         0;
    :local  txSpeed         0;
    :local  message         "   Bandwidth test report on ";
    :local  currentDate   ([/system clock get date]." ".[/system clock get time]);
    :set    message        ($message.$currentDate.":");
    :log    warning        ($message);
    :set    message        ($message."\r\n");
    if ($localUser != "" && $localPassword != "" && $nameVPN != "") do={
        :foreach activeVPN in=[ /ip address find interface~$nameVPN; ] do={
            :do {
                :local remoteAddress [ /ip address get $activeVPN network;   ];
                :local localAddress  [ /ip address get $activeVPN address;   ];
                :local interfaceVPN  [ /ip address get $activeVPN interface; ];
                :local staticIP      "                  ";
                :do { :set staticIP  [ /ip route get [ find gateway=$interfaceVPN static=yes ] dst-address]; } on-error={ }
                :local checkPing     [ /ping $remoteAddress src-address=[ :pick $localAddress 0 ([ :len $localAddress ] - 3)] count=$countPing; ];
                :if ($checkPing < ($countPing / 3 * 2)) do={
                    :log warning (         "Test of '$interfaceVPN' is fail, active interface not responded."    ); 
                    :set message ("$message Test of '$interfaceVPN' is fail, active interface not responded.\r\n");
                } else={
                    /tool bandwidth-test address=$remoteAddress duration=10s protocol=tcp user=$localUser password=$localPassword direction=both do={
                        :set rxSpeed ([$"rx-total-average"]);
                        :set txSpeed ([$"tx-total-average"]);
                    }
                    :local simpleMbRxReport ($rxSpeed / 1000000);
                    :local simpleMbTxReport ($txSpeed / 1000000);
                    :local lowMbRxReport  ((($rxSpeed - ($simpleMbRxReport * 1000000)) * 1000000) / 1000);
                    :local lowMbTxReport  ((($txSpeed - ($simpleMbTxReport * 1000000)) * 1000000) / 1000);
                    :local mbRxReport        "";
                    :local mbTxReport        "";
                    if ($simpleMbRxReport < 100) do={ if ($simpleMbRxReport < 10) do={ :set mbRxReport ("  "); } else={ :set mbRxReport (" "); } }
                    if ($simpleMbTxReport < 100) do={ if ($simpleMbTxReport < 10) do={ :set mbTxReport ("  "); } else={ :set mbTxReport (" "); } }
                    :set mbRxReport ("$mbRxReport$simpleMbRxReport.$[:pick $lowMbRxReport 0 2]");
                    :set mbTxReport ("$mbTxReport$simpleMbTxReport.$[:pick $lowMbTxReport 0 2]");
                    :set interfaceVPN  ([:pick "'$interfaceVPN':                            " 0 41]);
                    :set remoteAddress ([:pick "$remoteAddress                              " 0 19]);
                    :set staticIP      ([:pick "$staticIP                                   " 0 19]); 
                    :set mbRxReport    ([:pick "$mbRxReport Mbps,                           " 0 12]);
                    :set mbTxReport    ([:pick "$mbTxReport Mbps.                           " 0 12]);
                    :set message ("$message test to $interfaceVPN $remoteAddress $staticIP => Rx: $mbRxReport  Tx: $mbTxReport\r\n");
                    :log warning (         "test to $interfaceVPN $remoteAddress $staticIP => Rx: $mbRxReport  Tx: $mbTxReport"    );
                } 
            } on-error={ :log warning ("Script error. Not found some $nameVPN interfaces."); } 
        } 
    } else={ :set message ("$message Script error. Check variables: localUser, localPassword, nameVPN.\r\n"); }
    :if ($fileName != "") do={
        :if ( [:len [/file find name=$fileName]] = 0) do={ /file print file=$fileName where name=""; }
        :do { /file set $fileName contents=($message."\r\n".[get $fileName contents]); } on-error={ }
    } else={ :set message ("$message File name undefined - no output to file. Check variable fileName.\r\n"); }
    :log warning         ("   End of bandwidth test.");
    :set message ("$message   End of bandwidth test.\r\n");
    :put ($message);
}



Переменная localUser содержит имя пользователя.
Переменная localPassword содержит пароль пользователя.
Переменная nameVPN содержит общую часть названия требуемых VPN-интерфейсов.
Можно указать переменную fileName, тогда вывод будет дублироваться в указанный файл.


yuriy.shevchik
Сообщения: 1
Зарегистрирован: 13 июл 2021, 12:30

Спасибо


Аватара пользователя
drpioneer
Сообщения: 142
Зарегистрирован: 30 май 2013, 10:20

Версия скрипта, работающая и под ROS6, и под ROS7:

Код: Выделить всё




# Script for determining the bandwidth of VPN interfaces
# Script uses ideas by druide, Sertik, drPioneer
# https://forummikrotik.ru/viewtopic.php?t=5986
# tested on ROS 6.49.10 & 7.12
# updated 2023/12/29

:do {
    :local user "";
    :local pswd "";
    :local countPing 2;
    :local message "Bandwidth report from '$[system identity get name]':";

    # --------------------------------------------------------------------------------- # digit conversion function via SI-prefix
    :local NumSiPrefix do={
        :local inp [:tonum $1]; :local cnt 0;
        :while ($inp>1000) do={:set $inp ($inp/1000); :set $cnt ($cnt+1)}
        :return ($inp.[:pick [:toarray "Bps,Kbps,Mbps,Gbps,Tbps,Pbps,Ebps,Zbps,Ybps"] $cnt]);
    }

    # ================================================================================= # main body of the script ========================
    :local routeISP [/ip route find];                                                   # gateways information
    :if ($user!="" && $pswd!="" && [:len $routeISP]>0) do={
        :local gwList [:toarray ""]; :local count 0;
        :foreach idEth in=[/interface ethernet find] do={                               # list of ethernet interfaces
            :set ($gwList->$count) [/interface ethernet get $idEth name];
            :set count ($count+1);
        }
        :local ethCount $count;
        :foreach inetGate in=$routeISP do={                                             # enumeration of gateways
            :local gwName [:tostr [/ip route get $inetGate gateway]];
            :if ([:len $gwName]>0) do={
                :local ifaceISP "";                                                     # formation of interface name
                :foreach idName in=[/interface find running=yes] do={
                    :local ifName [/interface get $idName name];
                    :if ([:len [find key=$ifName in=$gwName]]>0) do={:set ifaceISP $ifName}
                }
                :if ([:len $ifaceISP]>0) do={
                    :if ([:len [/interface bridge find name=$ifaceISP]]>0) do={         # checking the interface for entering the Bridge
                        :if ([:find $gwName "%"]>0) do={
                            :set $gwName [:pick $gwName ([:len [:pick $gwName 0 [:find $gwName "%"]]] +1) [:len $gwName]];
                        }
                        :if ($gwName~"((25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)[.]){3}(25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)") do={
                            :local mcAddrGate [/ip arp get [find address=$gwName interface=$ifaceISP] mac-address];
                            :if ($mcAddrGate~"([0-9A-F]{2}[:]){5}[0-9A-F]{2}") do={
                                :set ifaceISP [/interface bridge host get [find mac-address=$mcAddrGate] interface];
                            } else={:set ifaceISP ""}
                        } else={:set ifaceISP ""}
                    }
                    :if ([:len $ifaceISP]>0) do={
                        :local checkIf [:len [find key=$ifaceISP in=$gwList]];          # checking the repetition of interface name
                        :if ($checkIf=0) do={
                            :set ($gwList->$count) $ifaceISP;
                            :set count ($count+1);
                            :local remAddr [/ip address get [find interface=$ifaceISP] network];
                            :local locAddr [/ip address get [find interface=$ifaceISP] address];
                            :local chkPing [/ping $remAddr src-address=[:pick $locAddr 0 ([:len $locAddr]-3)] count=$countPing];
                            :if ($chkPing<($countPing/3*2)) do={:set message "$message \r\n'$ifaceISP' is fail, interface not responded.";
                            } else={
                                :local rxSpeed ""; :local txSpeed "";
                                /tool bandwidth-test address=$remAddr duration=5s protocol=tcp user=$user password=$pswd direction=receive  do={:set rxSpeed [$NumSiPrefix [$"rx-total-average"]]}
                                /tool bandwidth-test address=$remAddr duration=5s protocol=tcp user=$user password=$pswd direction=transmit do={:set txSpeed [$NumSiPrefix [$"tx-total-average"]]}
                                :set message "$message\r\n'$ifaceISP' $rxSpeed/$txSpeed (Rx/Tx)";
                            }
                        }
                    }
                }
            }
        }
        :if ($ethCount=$count) do={:set message "$message \r\nNo active VPN-routes"}
    } else={:set message "$message \r\nEmpty variables 'user','pswd' or no active routes"}
    :put $message;                                                                      # output of message
    log warning $message;
} on-error={ :log warning "Error, can't show bandwidth test"}


Переменные user/pswd хранят логин/пароль для встроенного BTestServer.


Аватара пользователя
drpioneer
Сообщения: 142
Зарегистрирован: 30 май 2013, 10:20

Приветствую всех!
Представляю вариант скрипта проверки ширины каналов с использованием встроенных в RouterOS тестов 'PingSpeed' и 'BandWidth':

Код: Выделить всё



# Script for determining bandwidth of channel
# Script uses ideas by druide, Sertik, drPioneer
# https://forummikrotik.ru/viewtopic.php?t=5986
# tested on ROS 6.49.10 & 7.12
# updated 2024/02/12

:do {
  :local myFile "";   # file name, for example "bandwidth.txt";
  :local listIP {
    {name="MkBwTst"; ip=23.162.144.120; user="MikrotikBtest"; pswd="MikrotikBtest"; prot="tcp"};
    {name="Neterra"; ip=87.121.0.45; user="neterra"; pswd="neterra"; prot="tcp"};
    {name="Google";  ip=173.194.221.138; user=""; pswd=""; prot="tcp"};
#    {name="MyVPN"; ip=192.168.1.10; user="test"; pswd="test"; prot="tcp"};
  }

  # channel speed measurement function --------------------------------------------------
  :local BandWidthTest do={
    # digit conversion function via SI-prefix -------------------------------------------
    :local NumSiPrefix do={
      :if ([:len $1]=0) do={:return "0Bps"}
      :local inp [:tonum $1]; :local cnt 0;
      :while ($inp>1000) do={:set $inp ($inp/1000); :set $cnt ($cnt+1)}
      :return ($inp.[:pick [:toarray "Bps,Kbps,Mbps,Gbps,Tbps,Pbps,Ebps,Zbps,Ybps"] $cnt]);
    }
    :local rxSpd ""; :local txSpd ""; :local rxSts ""; :local txSts ""; :local pngTst;
    /tool ping-speed address=$1 duration=11 do={:set pngTst [$NumSiPrefix [$"average"]]}
    :local outMsg "PingSpeedTest:\t$pngTst\tBandWidthTest via $4:";
    /tool bandwidth-test address=$1 user=$2 password=$3 protocol=$4 direction="receive" duration=5 do={
      :set rxSpd [$NumSiPrefix [$"rx-total-average"]]; :set rxSts [$"status"];
    }
    /tool bandwidth-test address=$1 user=$2 password=$3 protocol=$4 direction="transmit" duration=5 do={
      :set txSpd [$NumSiPrefix [$"tx-total-average"]]; :set txSts [$"status"];
    }
    :if ($rxSts=$txSts) do={:if ($rxSts~"done") do={:return "$outMsg\t$rxSpd/$txSpd(Rx/Tx)"} else={:return "$outMsg\t$rxSts"}}
    :if ($txSts~"done") do={:return "$outMsg\t$rxSts"}
    :if ($rxSts~"done") do={:return "$outMsg\t$txSts"}
    :return "$outMsg\tunknown error";
  }

  # main body of script -----------------------------------------------------------------
  :global outBndWdt "Bandwidth report from $[system identity get name]:";
  :if ([:len $listIP]>0) do={
    :foreach testCh in=$listIP do={
      :local remNam ($testCh->"name");
      :local remUsr ($testCh->"user"); :local remPsw ($testCh->"pswd");
      :local remPrt ($testCh->"prot"); :local remAdr ($testCh->"ip");
      :put ("> Test to '$remNam' ($remAdr) via $remPrt:");
      :local pngCnt [/ping $remAdr count=3];
      :if ($pngCnt<2) do={:set outBndWdt "$outBndWdt\r\n> $remNam\t$remAdr\tis fail, address not responded";
      } else={:set outBndWdt "$outBndWdt\r\n> $remNam\t$remAdr\t$[$BandWidthTest $remAdr $remUsr $remPsw $remPrt]"}
    }
  } else={:set outBndWdt "$outBndWdt\r\n> Test is not possible, list of IP-addresses is empty"}
  :put ("-----------------------------------------------------------------------------------------------------\r\n$outBndWdt");
  :log warning $outBndWdt;
  :if ([:len $myFile]!=0) do={
    :local fileName ("$[/system identity get name]_$myFile");
    :execute script=":global outBndWdt; :put \"$outBndWdt\";" file=$fileName;
    :put ("File '$fileName' was successfully created");
  } else={:put ("File creation is not enabled")}
} on-error={:put "Error, can't show bandwidth test"; :log warning "Error, can't show bandwidth test"}
/system script environment remove [find name~"outBndWdt"];



Для полноценной проверки ширины каналов, на дальних концах должны быть настроены BTestServer'ы: Tools/BTestServer, Enabled=yes, Authenticate=yes. Без настроенных BTestServer'ов скрипт тоже покажет скоростные характеристики каналов за счёт теста 'PingSpeed', для этого дальние концы каналов должны Ping'оваться.

В скрипте необходимо заполнить список каналов по шаблону:
  • name="имя_канала"
  • ip=ip_адрес_дальнего_конца_канала
  • user="имя_пользователя_для_bandwidth_теста"
  • pswd="пароль_для_bandwidth_теста"
  • prot="протокол_для_bandwidth_теста_tcp_или_udp"
При запуске скрипта перебирается заданный список каналов и проводятся соответствующие тесты. По результатам тестов выводится полученная статистика. При указании имени файла в переменной 'myFile' результат также будет выводиться в файл.

Предлагаю заинтересованным потестить работу скрипта и отписать о замеченных проблемах.

Зеркало тут.

Удачи!


Ответить