initial commit

This commit is contained in:
Wifinigel 2023-01-19 21:27:15 +00:00
commit c782dde326
61 changed files with 1457 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
.vscode

View file

@ -0,0 +1,6 @@
{
# A simple script to print your Mikrotik board type
:local boardType [/system resource get board]
:put "Your Mikrotik board type is : $boardType"
}

View file

@ -0,0 +1,5 @@
# A simple script to print your Mikrotik board architecture
:local architectureName [/system resource get architecture-name]
#:put "Your Mikrotik board architecture is : $architectureName"
:log info "Your Mikrotik board architecture is : $architectureName"

View file

@ -0,0 +1,5 @@
# A simple script to print your Mikrotik board type
:local boardType [/system resource get board]
:put "Your Mikrotik board type is : $boardType"

View file

@ -0,0 +1,17 @@
# filename: ch10-01-bad-script.rsc
:local w {"mikrotik.com"; "www.google.com"; "twitter.com"};
:foreach s in=$w do={
:local i [/resolve $s];
:local p [/ping $i count=3 ];
:local u [/tool fetch url=("https://$s") mode=https http-method=get \
as-value keep-result=no];
:put "==========================================";
:put ("Site: $s");
:put ("IP Address = $i");
:put ("Ping success = $p/3");
:put ("Page d/load duration: " . $u->"duration");
:put "===========================================";
}

View file

@ -0,0 +1,29 @@
# filename: ch10-02-bad-script.rsc
#
# A simple script to perform a series of tests on a
# list of web sites.
# define list of websites to test
:local w {"mikrotik.com"; "www.google.com"; "twitter.com"};
# step through each website and perform various tests
:foreach s in=$w do={
# try a DNS resolution of this site
:local i [/resolve $s];
# try pinging the IP address of this site
:local p [/ping $i count=3 ];
# try fetching the web page of this site
:local u [/tool fetch url=("https://$s") mode=https http-method=get \
as-value keep-result=no];
# print out a summary report for this site
:put "==========================================";
:put ("Site: $s");
:put ("IP Address = $i");
:put ("Ping success = $p/3");
:put ("Page d/load duration: " . $u->"duration");
:put "===========================================";
}

View file

@ -0,0 +1,29 @@
# filename: ch10-03-bad-script.rsc
#
# A simple script to perform a series of tests on a
# list of web sites.
# define list of websites to test
:local WebSites {"mikrotik.com"; "www.google.com"; "twitter.com"};
# step through each website and perform various tests
:foreach SiteName in=$WebSites do={
# try a DNS resolution of this site
:local IpAddress [/resolve $SiteName];
# try pinging the IP address of this site
:local PingResult [/ping $IpAddress count=3 ];
# try getting the web page of this site
:local UrlFetch [/tool fetch url=("https://$SiteName") mode=https \
http-method=get as-value keep-result=no];
# print out a summary report for this site
:put "==========================================";
:put ("Site: $SiteName");
:put ("IP Address = $IpAddress");
:put ("Ping success = $PingResult/3");
:put ("Page d/load duration: " . $UrlFetch->"duration");
:put "===========================================";
}

View file

@ -0,0 +1,90 @@
:global Filename "ch10-04-bad-script.rsc"
# A simple script to perform a series of tests on a
# list of web sites.
# function to log error message
:global LogMessageFunc do={
:global Filename;
:local ErrorMessage ("$Filename: $1");
:log error $ErrorMessage;
:error $ErrorMessage;
}
# function to DNS resolve a site name to IP
:global DnsResolveFunc do={
:local WebSiteName $1;
:global LogMessageFunc;
# check arg type str of correct length passed
if (([:typeof $WebSiteName]!="str") or ([:len value=$WebSiteName] < 6)) do={
$LogMessageFunc ("DnsResolveFunc: arg value $WebSiteName not a valid \
string!");
}
return [/resolve $WebSiteName];
}
# function to ping an IP address 3 times
:global PingIpAddressFunc do={
:local IpAddress $1;
:global LogMessageFunc;
# check arg type ip is passed
if ([:typeof $IpAddress] != "ip") do={
$LogMessageFunc ("PingIpAddressFunc: arg value $IpAddress not an IP \
address!");
}
return [/ping $IpAddress count=3];
}
# function to return the result of fetching a web page
:global GetWebPageFunc do={
:local SiteName $1;
:global LogMessageFunc;
# check arg type str of correct length passed
if (([:typeof $SiteName] != "str") or ([:len value=$SiteName] < 6)) do={
$LogMessageFunc ("GetWebPageFunc: arg value $SiteName not a valid \
string!");
}
return [/tool fetch url=("https://$SiteName") mode=https http-method=get \
as-value keep-result=no];
}
##########
# Main
##########
# define list of websites to test
:local WebSites { "mikrotik.com"; "www.google.com"; "twitter.com"};
# step through each website and perform various tests
:foreach SiteName in=$WebSites do={
# try a DNS resolution of this site
:local IpAddress [$DnsResolveFunc $SiteName];
# try pinging the IP address of this site
:local PingResult [$PingIpAddressFunc $IpAddress];
# try getting the web page of this site
:local UrlFetch [$GetWebPageFunc $SiteName];
# print out a summary report for this site
:put "==========================================";
:put ("Site: $SiteName");
:put ("IP Address = $IpAddress");
:put ("Ping success = $PingResult/3");
:put ("Page d/load duration: " . $UrlFetch->"duration");
:put "===========================================";
}
# cleanup global namespace
:set Filename;
:set LogMessageFunc;
:set DnsResolveFunc;
:set PingIpAddressFunc;
:set GetWebPageFunc;

View file

@ -0,0 +1,7 @@
# ch10-05-error-check.rsc
:local WebSites { "badname1234.com"; "google.com"};
:foreach SiteName in=$WebSites do={
:local SiteIpAddress [/resolve $SiteName];
:put "Site IP for $SiteName is $SiteIpAddress";
}

View file

@ -0,0 +1,10 @@
# ch10-06-error-check.rsc
:local WebSites { "badname1234.com"; "google.com"};
:foreach SiteName in=$WebSites do={
:do {
:local SiteIpAddress [/resolve $SiteName];
:put "Site IP for $SiteName is $SiteIpAddress";
} on-error {
:put "Name lookup failed for $SiteName"
}
}

View file

@ -0,0 +1,115 @@
:global Filename "ch10-07-bad-script.rsc"
# A script to perform a series of tests on a
# list of web sites.
# function to log error messages
:global LogMessageFunc do={
:global Filename;
:local ErrorMessage "$Filename: $1";
:log error $ErrorMessage;
:put $ErrorMessage; # print to CLI
}
# function to DNS resolve a site name to IP
:global DnsResolveFunc do={
:local WebSiteName $1;
:global LogMessageFunc;
# check arg type str of correct length passed
:if (([:typeof $WebSiteName] != "str") or \
([:len value=$WebSiteName] < 6)) do={
$LogMessageFunc ("DnsResolveFunc: arg value $WebSiteName not a valid \
string!");
:return "*** test failed ***";
}
# try a name lookup
:do {
return [/resolve $WebSiteName];
} on-error={
$LogMessageFunc ("DnsResolveFunc: name resolution failed for site: \
$WebSiteName!");
:return "*** test failed ***";
}
}
# function to ping an IP address 3 times
:global PingIpAddressFunc do={
:local IpAddress $1;
:global LogMessageFunc;
# check arg type ip is passed
:if ([:typeof $IpAddress] != "ip") do={
$LogMessageFunc ("PingIpAddressFunc: arg value $IpAddress not an \
IP address!");
:return "*** test failed ***";
}
# try a ping
:do {
return [/ping $IpAddress count=3];
} on-error {
$LogMessageFunc ("PingIpAddressFunc: ping test failed: $IpAddress !");
:return "*** test failed ***";
}
}
# function to return the result of fetching a web page
:global GetWebPageFunc do={
:local SiteName $1;
:global LogMessageFunc;
# check arg type str of correct length passed
:if (([:typeof $SiteName] != "str") or ([:len value=$SiteName] < 6)) do={
$LogMessageFunc ("GetWebPageFunc: arg value $SiteName not a valid \
string!");
:return "*** test failed ***";
}
# try to get web page
:do {
:return [/tool fetch url=("https://$SiteName") mode=https \
http-method=get as-value keep-result=no];
} on-error {
$LogMessageFunc ("GetWebPageFunc: unable to retrieve site: \
$SiteName !");
:return { "duration"="*** test failed ***" }
}
}
##########
# Main
##########
# define list of websites to test
:local WebSites { "badsite1234.com"; "www.google.com"; "twitter.com"};
# step through each website and perform various tests
:foreach SiteName in=$WebSites do={
# try a DNS resolution of this site
:local IpAddress [$DnsResolveFunc $SiteName];
# try pinging the IP address of this site
:local PingResult [$PingIpAddressFunc $IpAddress];
# try getting the web page of this site
:local UrlFetch [$GetWebPageFunc $SiteName];
# print out a summary report for this site
:put "==========================================";
:put ("Site: $SiteName");
:put ("IP Address = $IpAddress");
:put ("Ping success = $PingResult/3");
:put ("Page d/load duration: " . $UrlFetch->"duration");
:put "===========================================";
}
# cleanup global namespace
:set Filename;
:set LogMessageFunc;
:set DnsResolveFunc;
:set PingIpAddressFunc;
:set GetWebPageFunc;

View file

@ -0,0 +1,137 @@
:global Filename "ch10-08-bad-script.rsc"
# A script to perform a series of tests on a
# list of web sites.
# set DEBUG to "true" for script debugging output,
# "false" for normal operation
:global DEBUG false;
# debug function
:global DebugFunc do={
:global DEBUG;
:if ($DEBUG) do={ :put "**Debug: $1"; }
}
# function to log error messages
:global LogMessageFunc do={
:global Filename;
:local ErrorMessage "$Filename: $1";
:log error $ErrorMessage;
:put $ErrorMessage; # print to CLI
}
# function to DNS resolve a site name to IP
:global DnsResolveFunc do={
:local WebSiteName $1;
:global LogMessageFunc;
:global DebugFunc;
$DebugFunc "Entering DnsResolveFunc";
$DebugFunc ("Arg passed to func: $WebSiteName");
# check arg type str of correct length passed
$DebugFunc "Checking arg data type is correct";
:if (([:typeof $WebSiteName] != "str") or \
([:len value=$WebSiteName] < 6)) do={
:local ErrorMsg "DnsResolveFunc: arg value $WebSiteName not a valid \
string!";
$LogMessageFunc $ErrorMsg;
$DebugFunc $ErrorMsg;
:return "*** test failed ***";
} else={
$DebugFunc "Data type looks good";
}
:do {
$DebugFunc "Looking up IP of site name...";
:local SiteIpAddr [/resolve $WebSiteName];
$DebugFunc $SiteIpAddr;
:return $SiteIpAddr;
} on-error={
$DebugFunc "DNS lookup failed!";
$LogMessageFunc ("DnsResolveFunc: name resolution failed for site: \
$WebSiteName!");
:return "*** test failed ***";
}
}
# function to ping an IP address 3 times
:global PingIpAddressFunc do={
:local IpAddress $1;
:global LogMessageFunc;
# check arg type ip is passed
:if ([:typeof $IpAddress] != "ip") do={
$LogMessageFunc ("PingIpAddressFunc: arg value $IpAddress not an IP \
address!");
:return "*** test failed ***";
}
:do {
return [/ping $IpAddress count=3];
} on-error {
$LogMessageFunc ("PingIpAddressFunc: ping test to IP address failed: \
$IpAddress !");
:return "*** test failed ***";
}
}
# function to return the result of fetching a web page
:global GetWebPageFunc do={
:local SiteName $1;
:global LogMessageFunc;
# check arg type str of correct length passed
if (([:typeof $SiteName] != "str") or ([:len value=$SiteName] < 6)) do={
$LogMessageFunc ("GetWebPageFunc: arg value $SiteName not a valid \
string!");
:return { "duration"="*** test failed ***" };
}
do {
return [/tool fetch url=("https://$SiteName") mode=https http-method=get \
as-value keep-result=no];
} on-error {
$LogMessageFunc ("GetWebPageFunc: unable to retrieve site: $SiteName !");
return { "duration"="*** test failed ***" };
}
}
##########
# Main
##########
# define list of websites to test
:local WebSites { "badsite1234.com"; "www.google.com"; "twitter.com"};
# step through each website and perform various tests
:foreach SiteName in=$WebSites do={
# try a DNS resolution of this site
:local IpAddress [$DnsResolveFunc $SiteName];
# try pinging the IP address of this site
:local PingResult [$PingIpAddressFunc $IpAddress];
# try getting the web page of this site
:local UrlFetch [$GetWebPageFunc $SiteName];
# print out a summary report for this site
:put "==========================================";
:put ("Site: $SiteName");
:put ("IP Address = $IpAddress");
:put ("Ping success = $PingResult/3");
:put ("Page d/load duration: " . $UrlFetch->"duration");
:put "===========================================";
}
# cleanup global namespace
:set Filename;
:set LogMessageFunc;
:set DnsResolveFunc;
:set PingIpAddressFunc;
:set GetWebPageFunc;
:set DEBUG;
:set DebugFunc;

View file

@ -0,0 +1,7 @@
# ch10-09-simple-pause.rsc
# A simple script that includes a 2 second pause
:put "Hello we're going to pause now...";
:delay 2;
:put "Pause complete. We're all done now!";

View file

@ -0,0 +1,27 @@
# ch10-10-add-remove-vlans.rsc
# a script to add and remove 50 VLANs to/from
# a Mikrotik router interface
: for VlanId from 200 to 249 do={
# find LAN interface ID
:local LanInterface "ether2";
:local LanInterfaceId [/interface find default-name=$LanInterface];
# add VLAN to LAN interface
:local VlanName "VLAN$VlanId";
/interface vlan add name="$VlanName" vlan-id=$VlanId \
interface=$LanInterfaceId;
}
: for VlanId from 200 to 249 do={
# find LAN interface ID
:local LanInterface "ether2";
:local LanInterfaceId [/interface find default-name=$LanInterface];
# add VLAN to LAN interface
:local VlanName "VLAN$VlanId";
/interface vlan remove "$VlanName";
}

View file

@ -0,0 +1,23 @@
# ch10-11-add-remove-vlans.rsc
# a script to add and remove 50 VLANs to/from
# a Mikrotik router interface
# find LAN interface ID
:local LanInterface "ether2";
:local LanInterfaceId [/interface find default-name=$LanInterface];
: for VlanId from 200 to 249 do={
# add VLAN to LAN interface
:local VlanName "VLAN$VlanId";
/interface vlan add name="$VlanName" vlan-id=$VlanId \
interface=$LanInterfaceId;
}
: for VlanId from 200 to 249 do={
# add VLAN to LAN interface
:local VlanName "VLAN$VlanId";
/interface vlan remove "$VlanName";
}

View file

@ -0,0 +1,31 @@
# ch10-12-add-remove-vlans.rsc
# a script to add and remove 50 VLANs to/from
# a Mikrotik router interface
# find LAN interface ID
:local LanInterface "ether2";
:local LanInterfaceId [/interface find default-name=$LanInterface];
:local AddLoopTime [:time {
: for VlanId from 200 to 249 do={
# add VLAN to LAN interface
:local VlanName "VLAN$VlanId";
/interface vlan add name="$VlanName" vlan-id=$VlanId \
interface=$LanInterfaceId;
}
}];
:put "Add loop time: $AddLoopTime";
:local RemoveLoopTime [:time {
: for VlanId from 200 to 249 do={
# add VLAN to LAN interface
:local VlanName "VLAN$VlanId";
/interface vlan remove "$VlanName";
}
}];
:put "Remove loop time: $RemoveLoopTime";

View file

@ -0,0 +1,6 @@
# filename: ch2-01-hello-world.rsc
# Hello World Script
/local Message "Hello World!";
/log info $Message;

View file

@ -0,0 +1,19 @@
# ch4-01-bad-ip-data-type.rsc
# Assign an IP address to a variable
:local InterfaceIp "192.168.99.2";
# Print out the variable contents
:put "The interface IP address in \$InterfaceIp is: $InterfaceIp";
# It looks like an IP address - let's check to make sure
:put ("The variable data type of \$InterfaceIp is: ". [:typeof $InterfaceIp]);
# Hmmmm...looks like we need to fix it
:local InterfaceIp [:toip $InterfaceIp];
# Let's print the fixed variable
:put "The interface IP address in \$InterfaceIp is now: $InterfaceIp";
# Let's check its data type
:put ("The variable data type of \$InterfaceIp is now: ". [:typeof $InterfaceIp]);

View file

@ -0,0 +1,14 @@
# ch4-02-ip-prefix-slicer.rsc
# Create a function to slice up an IP prefix
:global IpPrefixSlicerFunc do={
:local InterfaceIp ([/ip address get $1]->"address");
:local SlashPosition [:find $InterfaceIp "/"];
:local IpAddress [:pick $InterfaceIp 0 $SlashPosition];
:return [:toip $IpAddress]
}
# Run the function for ID *1 and verify data type of result
:local IpAddress [$IpPrefixSlicerFunc *1];
:put ("Result: $IpAddress");
:put ("Data type: " . [:typeof $IpAddress]);

View file

@ -0,0 +1,9 @@
# ch5-01-no-semi-colons.rsc
:local MULTIPLIER 10
:for Number from=1 to=10 do={
:local Result ($Number * $MULTIPLIER)
:put ("This is an unusually long line. Here is the result $Number times \
$MULTIPLIER is: $Result")
}

View file

@ -0,0 +1,9 @@
# ch5-02-semi-colons.rsc
:local MULTIPLIER 10;
:for Number from=1 to=10 do={
:local Result ($Number * $MULTIPLIER);
:put ("This is an unusually long line. Here is the result $Number times \
$MULTIPLIER is: $Result");
}

View file

@ -0,0 +1,10 @@
# filename: ch5-03-long-line.rsc
# Here is a long line
:put [/interface ethernet find where name~"ether" running true rx-fcs-error=0];
# Here is same line across multiple lines
:put [/interface ethernet find where \
name~"ether" \
running true \
rx-fcs-error=0];

View file

@ -0,0 +1,7 @@
# ch5-04-no-indentation.rsc
# Create an if-else statement with no additional indentation
:local DayOfWeek "Monday";
if ($DayOfWeek = "Monday") do={:put "Boo...it's Monday."
} else={:put "Yay! It's not Monday!"}

View file

@ -0,0 +1,10 @@
# ch5-05-indentation.rsc
# Create an if-else statement with no additional indentation
:local DayOfWeek "Monday";
if ($DayOfWeek = "Monday") do={
:put "Boo...it's Monday.";
} else={
:put "Yay! It's not Monday!";
}

View file

@ -0,0 +1,21 @@
# ch6-01-variable-value-test.rsc
# Declare a variable with no value
:local BridgeName;
# Test if the variable has a value
:if ([:typeof $BridgeName] = "nothing") do={
:put "Test 1: this variable has no value!";
} else= {
:put ("Test 1: the variable value is: $BridgeName");
}
# Set a value for the variable
:set BridgeName "Bridge1";
# Test if the variable has a value
:if ([:typeof $BridgeName] = "nothing") do={
:put "Test 2: this variable has no value!";
} else= {
:put ("Test 2: the variable value is: $BridgeName");
}

View file

@ -0,0 +1,14 @@
# ch6-02-undeclared-variable.rsc
# Declare a variable but assign no value
:local RouteDistance;
# Let's test the data type of the variable
:if ([:typeof $RouteDistance] = "nothing") do={
:put "Test 1: this variable has no value!";
}
# Let's test the data type of a non-existent variable
:if ([:typeof $RouteDist] = "nothing") do={
:put "Test 2: this variable has no value!";
}

View file

@ -0,0 +1,10 @@
# ---- global scope start ----
# filename: ch6-03-global-scope.rsc
# Let's create a variable in the global scope
:local GlobalScopeVar "I'm in the global scope!";
# Let's print it out
:put ("Global variable contents = $GlobalScopeVar");
# ---- global scope end ----

View file

@ -0,0 +1,26 @@
# ---- global scope start ----
# filename: ch6-04-local-scope.rsc
# Let's create a variable in the global scope
:local GlobalScopeVar "I'm in the global scope!";
{
# ---- start of a local scope ----
# Let's create a variable in this scope
:local LocalScopeVar "I'm in the local scope!";
# Let's print out the variable in this scope
:put ("Local scope variable contents = $LocalScopeVar");
# ---- end of local scope ----
}
# Let's print it out the global scope variable
:put ("Global scope variable contents = $GlobalScopeVar");
# Let's print out the local scope variable
# (hint: this won't work)
:put ("Local scope variable contents = $LocalScopeVar");
# ---- global scope end ----

View file

@ -0,0 +1,25 @@
# ---- global scope start ----
# filename: ch6-05-local-scope.rsc
# Let's create a variable in the global scope
:local GlobalScopeVar "I'm in the global scope!";
{
# ---- start of a local scope ----
# Let's create a variable in this scope
:local LocalScopeVar "I'm in the local scope!";
# Let's print out the variable in this scope
:put ("Local scope variable contents = $LocalScopeVar");
# Let's see if we can access the global scope variable
:put ("Global scope variable (in local scope) = $GlobalScopeVar");
# ---- end of local scope ----
}
# Let's print out the global scope variable
:put ("Global scope variable (in global scope) = $GlobalScopeVar");
# ---- global scope end ----

View file

@ -0,0 +1,33 @@
# filename: ch6-06-local-scope.rsc
# ---- start of a local scope ----
{
:local apple "green";
:local banana "yellow";
:put ("(1) The apple is: $apple");
:put ("(1) The banana is: $banana");
# ---- start of child local scope ----
{
:local apple "red";
:put ("(2) The apple is: $apple");
:put ("(2) The banana is: $banana");
}
# ---- end of child local scope ----
:put ("(3) The apple is: $apple");
:put ("(3) The banana is: $banana");
}
# ---- end of local scope ----
:put ("(4) The apple is: $apple");
:put ("(4) The banana is: $banana");
# ---- start of new local scope ----
{
:local apple "yellow";
:put ("(5) The apple is: $apple");
:put ("(5) The banana is: $banana");
}
# ---- end of new local scope ----

View file

@ -0,0 +1,13 @@
# filename: ch6-07-variable-types.rsc
# Create a local variable
:local Apple "green";
# Print its value
:put ("Local variable contents: $Apple");
# Create a global variable
:global Banana "green";
# Print its value
:put ("Global variable contents: $Banana");

View file

@ -0,0 +1,19 @@
# filename: ch6-08-local-vars.rsc
# Create a local variable
:local SmallNumber;
# Print its value
:put ("Variable contents: $SmallNumber");
# Assign some data to the variable
:set SmallNumber 2
# Print its value again
:put ("Variable contents: $SmallNumber");
# Let's change the variable value
:set SmallNumber 3
# Print its value again
:put ("Variable contents: $SmallNumber");

View file

@ -0,0 +1,20 @@
# filename: ch6-09-local-vars2.rsc
# Create a local variable that is an array of words
:local Words { "Hello, "; "how "; "are "; "you ?"};
# Create a local variable to store concatenated words in a string
:local WordString;
# Step through each word and add to the "WordString" variable
:foreach Word in=$Words do={
:put "Word from array: $Word";
:set WordString ($WordString . $Word);
}
# Print out the result
:put "\n";
:put "New string we've built:";
:put $WordString;
:put "\n";
:put ("Original array: " . [:tostr $Words]);

View file

@ -0,0 +1,36 @@
# filename: ch6-10-global-vars.rsc
# Note: this script assumes global vars $Day,
# $Month and $Year have been set via the CLI
#
# Let's get a dump of our current global variables:
:environment print;
# Let's check we can access each variable:
:put "The day today is $Day";
:put "The month today is $Month";
:put "The year today is $Year";
# Uh-oh...we had an issue, no values were printed!
:put "\nThat didn't work!\n";
# To access global variables declared outside our script
# we need to declare them again within our script, but do
# not assign a value when declaring them:
:global Day;
:global Month;
:global Year
# Let's try printing them again:
:put "The day today is $Day";
:put "The month today is $Month";
:put "The year today is $Year";
# Let's declare a new global variable to
# access outside of this script:
:global TimeOfDay "morning";
:global Breakfast "muesli";
# Lets get a dump of our current global variables:
:put "\nCurrent global variables:\n";
:environment print;

View file

@ -0,0 +1,32 @@
# filename: ch6-11-global-vars2.rsc
# Lets get a dump of our current global variables:
:environment print;
# Let's declare a new global variable
:global Beverage "coffee";
# Let's declare global vars that already exist so that
# we may access them
:global Fruit;
:global TellTheTruth;
# Let's print modify the vars if we no not
# wish to tell the truth
if ($TellTheTruth = false) do={
:set Fruit "bananas";
:set Beverage "beer";
}
# Let's see which are my favourite fruit and
# beverage
:put "My favourite fruit is: $Fruit";
:put "My favourite beverage is: $Beverage";
if ($TellTheTruth = false) do={
:put "(pssst...this is actually a lie)";
}
# Lets get a dump of our current global variables:
:put "\nCurrent global variables:\n";
:environment print;

View file

@ -0,0 +1,37 @@
# filename: ch6-12-global-vars3.rsc
# In this script, we expect to have several interface names
# in a global variable called "WanInterfaces". The variable
# should be an array for the script to work correctly
# Declare the "WanInterfaces" global variable to access
# its data (assuming it exists)
:global WanInterfaces;
# Does it have a value? If not, exit with an error
if ( [:typeof $WanInterfaces] = "nothing") do={
:error "The WanInterfaces global variable is not set. Exiting"
}
# Is the variable an array data type?
if ( [:typeof $WanInterfaces] != "array") do={
:error "The WanInterfaces global variable is not an array data type. Exiting."
}
# Let's step through the interfaces in the array
# and print out their operation status
:foreach WanInterface in=$WanInterfaces do={
:local InterfaceIndex [/interface ethernet find name=$WanInterface];
:local UpDown "down";
if ([:interface ethernet get $InterfaceIndex]->"running") do={
:set UpDown "up"
}
:put "Interface $WanInterface is currently $UpDown";
}
# Let's assume no-one else will need the "WanInterfaces"
# variable. Let's remove it from global variables
:set WanInterfaces;

View file

@ -0,0 +1,16 @@
# filename: ch7-01-basic-if.rsc
# Print a greeting
:put "Hello, I hope you're well.";
# Check if the time is after 6pm (get time in 21:46:04 format)
:local CurrentTime [:system clock get time];
:put "The current time is : $CurrentTime";
# Say good evening if time is after 18:00
:if ($CurrentTime > 18:00) do={
:put "Good evening!";
}
# Say goodbye
:put "Thanks for visiting, bye!";

View file

@ -0,0 +1,28 @@
# filename: ch7-02-basic-if.rsc
# Create a variable for the WAN interface name
:local WanInterface "ether1-WAN";
# Create a variable for the number of pings we'd like to send
:local PingCount 10;
# Create a variable for the destination on the Internet to ping
:local DestinationAddress 8.8.8.8;
# Let's try a ping to the Internet across the WAN interface
:local WanPingCount [/ping $DestinationAddress interface=$WanInterface \
count=$PingCount];
# Let's log the result of our Internet connection test
if ( $WanPingCount = $PingCount) do={
:log info "The Internet is up.";
}
if ( $WanPingCount = 0) do={
:log error "The Internet is down.";
}
if ( ($WanPingCount < $PingCount) and ($WanPingCount > 0) ) do={
:log warning "The Internet connection may be degraded. (Ping result: $WanPingCount/$PingCount)";
}

View file

@ -0,0 +1,18 @@
# filename: ch7-03-if-else.rsc
# Print a greeting
:put "Hello, I hope you're well.";
# Check if the time is after 6pm (get time in 21:46:04 format)
:local CurrentTime [:system clock get time];
:put "The current time is : $CurrentTime";
# Say good morning if time is before 12:00
:if ($CurrentTime > 12:00) do={
:put "Good day!";
} else={
:put "Good morning!"
}
# Say goodbye
:put "Thanks for visiting, bye!";

View file

@ -0,0 +1,16 @@
# filename: ch7-04-if-else-vars.rsc
# Get the current time
:local CurrentTime [:system clock get time];
:put "The current time is : $CurrentTime";
# Check if it's after noon
:if ($CurrentTime > 12:00) do={
:local TimeOfDay "Afternoon/Evening"
} else={
# otherwise, it must be morning (00:00 to 11:59)
:local TimeOfDay "Morning"
}
# Print out the time of day
:put "At the moment, it's : $TimeOfDay"

View file

@ -0,0 +1,19 @@
# filename: ch7-05-if-else-vars2.rsc
# Get the current time
:local CurrentTime [:system clock get time];
:put "The current time is : $CurrentTime";
# declare the time of day variable
:local TimeOfDay
# Check if it's after noon
:if ($CurrentTime > 12:00) do={
:set TimeOfDay "Afternoon/Evening"
} else={
# otherwise, it must be morning (00:00 to 11:59)
:set TimeOfDay "Morning"
}
# Print out the time of day
:put "At the moment, it's : $TimeOfDay"

View file

@ -0,0 +1,28 @@
# filename: ch7-06-multiple-conditions.rsc
# Get the current time
:local CurrentTime [:system clock get time];
:put "The current time is : $CurrentTime";
# declare the time of day variable
:local TimeOfDay
# Check if it's very early
:if (($CurrentTime >= 00:00) and ($CurrentTime < 06:00)) do={
:put "It's very early in the morning...shouldn't you be in bed?";
}
# Check if its morning
:if (($CurrentTime >= 06:00) and ($CurrentTime < 12:00)) do={
:put "Good morning!";
}
# Check if its afternoon
:if (($CurrentTime >= 12:00) and ($CurrentTime < 17:00)) do={
:put "Good afternoon!";
}
# check if its evening
:if (($CurrentTime >= 17:00) and ($CurrentTime < 00:00)) do={
:put "Good evening!";
}

View file

@ -0,0 +1,37 @@
# filename: ch7-07-nested-if-statements.rsc
# Get the current time
:local CurrentTime [:system clock get time];
:put "The current time is : $CurrentTime";
# declare the time of day variable
:local TimeOfDay
# Check if it's before noon
:if ($CurrentTime < 12:00) do={
# it's before noon, let's see what time of the morning
# it is using a nested if-else statement
if ($CurrentTime < 06:00) do={
:set TimeOfDay "It's very early in the morning...shouldn't you be in bed?";
} else={
# it must be between 06:01 and 11:59 to reach here
:set TimeOfDay "Good morning!";
}
# end of nested if-else statement
} else={
# it must be after noon, let's see if it's evening or
# afternoon using a nested if-else statement
if ($CurrentTime < 18:00) do={
:set TimeOfDay "Good afternoon!";
} else={
# it must be between 18:00 and 23:59 to reach here
:set TimeOfDay "Good evening!";
}
# end of nested if-else statement
}
:put $TimeOfDay;

View file

@ -0,0 +1,17 @@
# filename: ch7-08-if-else-binary.rsc
# define WAN interface name
:local WanInterfaceName "ether1-WAN";
# find the interface index
:local InterfaceIndex [/interface ethernet find name=$WanInterfaceName];
:local UpDown;
if ([:interface ethernet get $InterfaceIndex]->"running") do={
:set UpDown "up"
} else={
:set UpDown "down"
}
:put "Interface $WanInterfaceName is currently $UpDown";

View file

@ -0,0 +1,14 @@
# filename: ch7-09-if-binary-simplified.rsc
# define WAN interface name
:local WanInterfaceName "ether1-WAN";
# find the interface index
:local InterfaceIndex [/interface ethernet find name=$WanInterfaceName];
:local UpDown "down";
if ([:interface ethernet get $InterfaceIndex]->"running") do={
:set UpDown "up"
}
:put "Interface $WanInterface is currently $UpDown";

View file

@ -0,0 +1,12 @@
# filename: ch8-01-for-basic.rsc
# Let's print out a series of numbers and part of
# the 12 times table
:for LoopCount from=1 to=5 do={
:put ("Current loop counter is: $LoopCount");
:put ("12 x $LoopCount is: " . (12 * $LoopCount));
}
# Print out the final loop count (fails!)
:put ("Final loop count is: " . $LoopCount);

View file

@ -0,0 +1,20 @@
# filename: ch8-02-for-check-web.rsc
# define an array of web sites
:local WebSites {"mikrotik.com"; "google.com"; "twitter.com"};
# use a simple for loop to check if each site is reachable
:for SiteIndex from=0 to=2 do={
:local Site ($WebSites->$SiteIndex);
:put "Pinging web site: $Site";
:local PingResult [/ping $Site count=3 ];
:if ($PingResult > 0) do {
:put ("\nWeb site $Site reached OK\n");
} else={
:put ("\nNo response from web site: $Site\n");
}
}

View file

@ -0,0 +1,15 @@
# ch8-03-for-create-vlan.rsc
# define the interface where we'd like to add a VLAN
# !! Set this to a valid interface name on your Mikrotik !!
:local InterfaceName "ether5";
# create a for loop with a step of 10
:for VlanId from=100 to=150 step=10 do={
:put ("Creating VLAN $VlanId on interface $InterfaceName");
:local VlanName ("vlan" . $VlanId);
/interface vlan add name=$VlanName vlan-id=$VlanId interface=$InterfaceName;
}

View file

@ -0,0 +1,18 @@
# filename: ch8-04-foreach-web.rsc
# define an array of web sites
:local WebSites {"mikrotik.com"; "google.com"; "twitter.com"};
# use a foreach loop to check if each site is reachable
:foreach Site in=$WebSites do={
:put "Pinging web site: $Site";
:local PingResult [/ping $Site count=3 ];
:if ($PingResult > 0) do {
:put ("\nWeb site $Site reached OK\n");
} else={
:put ("\nNo response from web site: $Site\n");
}
}

View file

@ -0,0 +1,9 @@
# filename: ch8-05-foreach-kv.rsc
# define an array of interface data
:local InterfaceErrors {"WAN"=514; "LAN"=0; "ether3"=0; "ether4"=0; 5};
# use a foreach loop to print out the error value for each interface
:foreach InterfaceName,ErrorCounter in=$InterfaceErrors do={
:put "$InterfaceName errors: $ErrorCounter";
}

View file

@ -0,0 +1,20 @@
# filename: ch8-06-while-infinite.rsc
# Let's create an infinite loop using "while"
:local LoopCounter 5;
:while ($LoopCounter <= 10) do={
# print out the current loop counter value
:put "Value of loop counter is: $LoopCounter";
# decrement the counter
:set LoopCounter ($LoopCounter - 1);
# add in a pause to prevent cpu thrashing
delay 1;
}
# print a message when/if the loop exits
:put "Loop has exited!";

View file

@ -0,0 +1,17 @@
# filename: ch8-06-while-with-exit.rsc
# Let's create a loop using "while"
:local LoopCounter 5;
:while ($LoopCounter <= 10) do={
# print out the current loop counter value
:put "Value of loop counter is: $LoopCounter";
# increment the counter
:set LoopCounter ($LoopCounter + 1);
}
# print a message when/if the loop exits
:put "Loop has exited!";

View file

@ -0,0 +1,34 @@
# ch8-08-while-timer.rsc
# script to report page load time of google.com
# get the current time
:local CurrentTime [/system clock get time];
# calculate the time in 1 minute
:local EndTime ($CurrentTime + 00:01:00);
# define a target web site
:local WebSite "www.google.com";
# run a while loop until one minute interval expired
:while ( [/system clock get time] < $EndTime ) do={
:put "Getting web page from $WebSite";
# fetch a page from web site
:local FetchResult [/tool fetch url=("https://$WebSite") mode=https \
http-method=get as-value keep-result=no];
if ($FetchResult->"status" = "finished") do={
# print out how long page retrieval took (if successful)
:local FetchDuration ($FetchResult->"duration");
:put "Web page fetch time: $FetchDuration secs";
} else={
:put "Web page fetch failed";
}
# pause for 5 seconds
:delay 5;
}

View file

@ -0,0 +1,18 @@
# filename: ch8-09-while-alt-form.rsc
# Let's create a loop using "while"
:local LoopCounter 5;
:do {
# print out the current loop counter value
:put "Value of loop counter is: $LoopCounter";
# increment the counter
:set LoopCounter ($LoopCounter + 1);
} while ($LoopCounter <= 4)
# print a message when/if the loop exits
:put "Loop has exited!";

View file

@ -0,0 +1,25 @@
# filename: ch9-01-mac-fixer.rsc
# Let's create function to remove colon characters
# from a MAC address passed as an argument
# --- start of function ---
:global MacColonRemoveFunc do={
:local TidyMac "";
for i from=0 to=([:len $1]-1) do={
:local TmpValue [:pick $1 $i];
:if ($TmpValue !=":") do={ :set TidyMac "$TidyMac$TmpValue" }
}
:return $TidyMac;
}
# --- end of function ---
# Now, let's call the function with some values
:local MacAddress "00:08:EF:44:98:18"
:put ("$MacAddress becomes: " . [$MacColonRemoveFunc $MacAddress]);
:set MacAddress "DC:2C:6E:DF:D5:F6"
:put ("$MacAddress becomes: " . [$MacColonRemoveFunc $MacAddress]);
# Cleanup global namespace
:set MacColonRemoveFunc;

View file

@ -0,0 +1,39 @@
# filename: ch9-02-multiple-args-simple.rsc
# Let's create function to receive multiple args
# --- start of function ---
:global PrintInterfaceAttrsFunc do={
:local InterfaceName $1;
:local InterfaceSpeed $2;
:local InterfaceIp $3;
# check args are correct data types
if ([:typeof $InterfaceName] != "str") do={
:error "Interface name argument not a string!";
}
if ([:typeof $InterfaceSpeed] != "str") do={
:error "InterfaceSpeed argument not a string!";
}
if ([:typeof $InterfaceIp] != "str") do={
:error "Interface IP argument not a string!";
}
# data type checks passed, print the interface data
:put "$InterfaceName: IP address = $InterfaceIp, speed = $InterfaceSpeed";
}
# --- end of function ---
# Let's call the function with some sample values ($1, $2, $3)
$PrintInterfaceAttrsFunc "WAN1" "100Mbps" "192.168.99.1/24";
# Let's call the function with some other values ($1, $2, $3)
$PrintInterfaceAttrsFunc "ether2-LAN" "1000Mbps" "172.16.1.254/24";
# Cleanup global namespace
:set PrintInterfaceAttrsFunc;

View file

@ -0,0 +1,44 @@
# filename: ch9-03-multiple-args-array.rsc
# Let's create function to receive a single array arg
# --- start of function ---
:global PrintInterfaceAttrsFunc do={
if ([:typeof $1] != "array") do={
:error "Function argument is not an array!";
}
:local Args $1;
:local InterfaceName ($Args->"ifname");
:local InterfaceSpeed ($Args->"ifspeed");
:local InterfaceIp ($Args->"ifip");
# check args are correct data types
if ([:typeof $InterfaceName] != "str") do={
:error "InterfaceName argument not a string!";
}
if ([:typeof $InterfaceSpeed] != "str") do={
:error "InterfaceSpeed argument not a string!";
}
if ([:typeof $InterfaceIp] != "str") do={
:error "InterfaceIp argument not a string!";
}
# data type checks passed, print the interface data
:put "$InterfaceName: IP address = $InterfaceIp, speed = $InterfaceSpeed";
}
# --- end of function ---
# Let's call the function with some sample values in an array
:local Args { ifname="WAN1"; ifspeed="100Mbps"; ifip="192.168.99.1/24" };
$PrintInterfaceAttrsFunc $Args;
# Let's call the function with some other values in an array
:set Args { ifname="ether2-LAN"; ifspeed="1000Mbps"; ifip="172.16.1.254/24" };
$PrintInterfaceAttrsFunc $Args;
# Cleanup global namespace
:set PrintInterfaceAttrsFunc;

View file

@ -0,0 +1,15 @@
# filename: ch9-04-create-global-func.rsc
# function to remove spaces from a string
#
# e.g. :local NoSpaceVar [$RemoveSpaceFunc "string with spaces"]
#
:global RemoveSpaceFunc do={
:local NewName ""
for i from=0 to=([:len $1]-1) do={
:local Tmp [:pick $1 $i]
:if ($Tmp !=" ") do={ :set NewName "$NewName$Tmp" }
}
:return $NewName
}
# --- end of function ---

View file

@ -0,0 +1,15 @@
# filename: ch9-05-use-global-func.rsc
# declare the name of the global function we wish to use
# to make it available in our script
:global RemoveSpaceFunc;
# creates a string that contains spaces
:local StringWithSpaces "txBroadcast = 201";
# print original string
:put ("String with spaces: $StringWithSpaces");
# print string that is modified by function
:local StringNoSpaces [$RemoveSpaceFunc $StringWithSpaces];
:put ("String with no spaces: $StringNoSpaces");

View file

@ -0,0 +1,24 @@
# filename: ch9-06-str-funcs-mod.rsc
# function to remove spaces from a string
#
# e.g. :local NoSpaceVar [$RemoveSpaceFunc "string with spaces"]
#
:global RemoveSpaceFunc do={
:local NewName ""
for i from=0 to=([:len $1]-1) do={
:local Tmp [:pick $1 $i]
:if ($Tmp !=" ") do={ :set NewName "$NewName$Tmp" }
}
:return $NewName
}
# --- end of function ---
# function to remove last char from a string
#
# e.g. :local choppedVar [$chopStrFunc "string with extra char,"]
#
:global ChopStrFunc do={
:return [ :pick $1 0 ( [ :len $1 ] -1 ) ];
}
# --- end of function ---

View file

@ -0,0 +1,30 @@
# filename: ch9-07-use-str-module.rsc
# import the functions we need and declare the function names we wish to use
/import "ch9-06-str-funcs-mod.rsc"
:global RemoveSpaceFunc;
:global ChopStrFunc;
# check our function names are valid
if ([:typeof $RemoveSpaceFunc] != "array") do={
:error "RemoveSpaceFunc is wrong data type or does not exist.";
}
if ([:typeof $ChopStrFunc] != "array") do={
:error "ChopStrFunc is wrong data type or does not exist.";
}
# create a string to use with the functions
:local StringToModify "txBroadcast = 201,";
# print original string
:put ("Orignal string: $StringToModify");
# use both functions to modify the string
:local ModifiedString [$RemoveSpaceFunc $StringToModify];
:set ModifiedString [$ChopStrFunc $ModifiedString];
:put ("Modified string: $ModifiedString");
# tidy up the global namespace (optional)
:set RemoveSpaceFunc;
:set ChopStrFunc;