9.1 KiB
Scripting examples - RouterOS - MikroTik Documentation
MikroTik RouterOS Scripting – Variables Cheat‑Sheet
Updated: 7 Aug 2025 Tested on RouterOS v7.15 (the syntax remains backward‑compatible to ≥ v6.48 unless explicitly noted).
Table of Contents
- Variable Declaration & Scope
- Data Types
- Inspecting Variables at Runtime
- Type Conversion & Casting
- Working with ip & ip‑prefix
- Arrays, Dictionaries & Nested Structures
- Common Pitfalls & Debug Tips
- Mini‑Cookbook (ready‑to‑use snippets)
- Quick Reference
1 Variable Declaration & Scope
Keyword | Visibility | Life‑time | Typical use |
---|---|---|---|
:global |
Global across all scripts executed by the same RouterOS user profile | Until it is explicitly unset with :set myVar or the router is rebooted |
Inter‑script state, cached look‑ups, long‑running counters |
:local |
Current scope only (the curly‑brace block, function, or interactive line that declared it) | Disappears as soon as execution leaves the block | Temporary loop counters, return values, throw‑away buffers |
:global buildDate "2025‑08‑07";
{
:local tmp [/system resource get uptime];
:put "Uptime = $tmp";
}
:put $tmp # -> *syntax error* (tmp is out of scope)
Each line you type in the interactive terminal acts as its own implicit local scope, so local variables are not visible to the next line (help.mikrotik.com).
Tip: If you need to read a global from inside a function, re‑declare it inside the function:
:global token "XYZ123" :global showToken do={ :global token; :return $token; }
2 Data Types
RouterOS recognises the following primitive data types: (help.mikrotik.com)
Type | Notes |
---|---|
num |
64‑bit signed integer (hex input with 0x allowed) |
bool |
true or false |
str |
UTF‑8 string |
ip |
IPv4 address (10.0.0.1 ) |
ip‑prefix |
IPv4 prefix (10.0.0.0/24 ) |
ip6 / ip6‑prefix |
IPv6 address or prefix |
id |
Internal hex ID (always starts with * ) |
time |
Absolute date‑time or time interval |
array |
Ordered list or key/value dictionary |
nil |
Unassigned / nothing (default when you declare without value) |
3 Inspecting Variables at Runtime
Task | Command |
---|---|
Show value | :put $myVar |
Show type | :put [:typeof $myVar] |
List all globals | /system script environment print |
Filter by name | /system script environment print where name="myVar" |
Example session:
:global newPrefix 192.0.2.0/24
:put [:typeof $newPrefix] # -> ip‑prefix
:put $newPrefix # -> 192.0.2.0/24
4 Type Conversion & Casting
Conversions are explicit; the shell will not silently cast between unrelated types (e.g. str ↔︎ ip‑prefix). Common helpers:
Function | Converts … |
---|---|
:tostr VALUE |
→ str |
:tonum VALUE |
→ num |
:toip VALUE |
→ ip / ip‑prefix |
:toarray VALUE |
→ array |
:tonothing / "" |
→ nil |
# Compare an address coming from CLI (string) with one stored as ip‑prefix
:local needle 111.111.1.1/24
/ip address print where address=[:tostr $needle] ;# OK
Trying to compare str
with ip‑prefix
directly fails for the same reason (find
returns nothing) (help.mikrotik.com).
5 Working with ip
& ip‑prefix
These types unlock bitwise operators, prefix‑matching, and membership tests:
:put (192.168.88.77 & 255.255.255.0) # subnet address
:put (192.168.1.5 in 192.168.0.0/16) # true
Calculating broadcast
:local net 192.168.88.0
:local mask 255.255.255.0
:local bcast ($net | (~$mask))
:put $bcast # -> 192.168.88.255
Avoiding string traps
Store prefixes as ip‑prefix
, not str
, whenever you intend to use routing / filter expressions.
Casting back to string is cheap: :tostr $prefix
.
6 Arrays, Dictionaries & Nested Structures
Create:
:global emptyArr [:toarray ""]
:global dict {user="admin"; pass="secret"}
Access / mutate:
:put ($dict->"user") # admin
:set ($dict->"pass") "p@ss!"
:set ($emptyArr->0) "first"
Multi‑dimensional arrays work the same:
:global matrix {{"11";"12"};{"21";"22"}}
:set ($matrix->1->0) "20"
See more idioms on the official “Tips & Tricks” page (help.mikrotik.com).
7 Common Pitfalls & Debug Tips
Gotcha | Fix |
---|---|
Using console numbers (set 0 name=LAN ) inside scripts |
Use .id or find , never buffer indexes (help.mikrotik.com) |
Comparing mismatched types (str vs ip‑prefix ) |
Cast with :tostr / :toip |
Shadowing globals inside functions | Re‑declare with :global myVar; inside the function |
Forgetting to unset unused globals | :set myVar (no value) to remove it (help.mikrotik.com) |
Non‑unique variable names (clashing with built‑ins) | Prefix your vars (e.g. my_ , ctx_ ) |
8 Mini‑Cookbook (ready‑to‑use snippets)
8.1 Detect & log WAN IP changes
:global currentIP
:local newIP [/ip address get [find interface="ether1"] address]
:if ($newIP != $currentIP) do={
:log info "IP changed $currentIP → $newIP"
:set currentIP $newIP
}
``` ([help.mikrotik.com](https://help.mikrotik.com/docs/spaces/ROS/pages/139067404/Scripting%2Bexamples))
### 8.2 Strip CIDR mask
```rsc
:local ipWithMask 10.1.101.1/24
:put [:pick $ipWithMask 0 [:find $ipWithMask "/"]]
8.3 Define an empty array
:global myArr [:toarray ""]
9 Quick Reference
Action | One‑liner |
---|---|
Declare global | :global gVar [value] |
Declare local | :local lVar [value] |
Change value | :set gVar newValue |
Unset variable | :set gVar |
Print value | :put $gVar |
Print type | :put [:typeof $gVar] |
Cast to string | :tostr $gVar |
Create prefix | :toip 192.0.2.0/24 |