225 lines
9.1 KiB
Markdown
225 lines
9.1 KiB
Markdown
***
|
||
|
||
[Scripting examples - RouterOS - MikroTik Documentation](https://help.mikrotik.com/docs/spaces/ROS/pages/139067404/Scripting+examples)
|
||
|
||
# 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
|
||
|
||
1. [Variable Declaration & Scope](#1-variable-declaration--scope)
|
||
2. [Data Types](#2-data-types)
|
||
3. [Inspecting Variables at Runtime](#3-inspecting-variables-at-runtime)
|
||
4. [Type Conversion & Casting](#4-type-conversion--casting)
|
||
5. [Working with *ip* & *ip‑prefix*](#5-working-with-ip--ip-prefix)
|
||
6. [Arrays, Dictionaries & Nested Structures](#6-arrays-dictionaries--nested-structures)
|
||
7. [Common Pitfalls & Debug Tips](#7-common-pitfalls--debug-tips)
|
||
8. [Mini‑Cookbook (ready‑to‑use snippets)](#8-mini-cookbook-ready-to-use-snippets)
|
||
9. [Quick Reference](#9-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 |
|
||
|
||
```rsc
|
||
: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](https://help.mikrotik.com/docs/spaces/ROS/pages/47579229/Scripting)).
|
||
|
||
> **Tip:** If you need to read a global from inside a function, *re‑declare* it inside the function:
|
||
>
|
||
> ```rsc
|
||
> :global token "XYZ123"
|
||
> :global showToken do={
|
||
> :global token;
|
||
> :return $token;
|
||
> }
|
||
> ```
|
||
|
||
---
|
||
|
||
## 2 Data Types
|
||
|
||
RouterOS recognises the following primitive data types: ([help.mikrotik.com](https://help.mikrotik.com/docs/spaces/ROS/pages/47579229/Scripting))
|
||
|
||
| 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:
|
||
|
||
```rsc
|
||
: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` |
|
||
|
||
```rsc
|
||
# 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](https://help.mikrotik.com/docs/spaces/ROS/pages/283574370/Scripting%2BTips%2Band%2BTricks)).
|
||
|
||
---
|
||
|
||
## 5 Working with `ip` & `ip‑prefix`
|
||
|
||
These types unlock bitwise operators, prefix‑matching, and membership tests:
|
||
|
||
```rsc
|
||
: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
|
||
|
||
```rsc
|
||
: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:
|
||
|
||
```rsc
|
||
:global emptyArr [:toarray ""]
|
||
:global dict {user="admin"; pass="secret"}
|
||
```
|
||
|
||
Access / mutate:
|
||
|
||
```rsc
|
||
:put ($dict->"user") # admin
|
||
:set ($dict->"pass") "p@ss!"
|
||
:set ($emptyArr->0) "first"
|
||
```
|
||
|
||
Multi‑dimensional arrays work the same:
|
||
|
||
```rsc
|
||
:global matrix {{"11";"12"};{"21";"22"}}
|
||
:set ($matrix->1->0) "20"
|
||
```
|
||
|
||
See more idioms on the official “Tips & Tricks” page ([help.mikrotik.com](https://help.mikrotik.com/docs/spaces/ROS/pages/283574370/Scripting%2BTips%2Band%2BTricks)).
|
||
|
||
---
|
||
|
||
## 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](https://help.mikrotik.com/docs/spaces/ROS/pages/283574370/Scripting%2BTips%2Band%2BTricks)) |
|
||
| 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](https://help.mikrotik.com/docs/spaces/ROS/pages/283574370/Scripting%2BTips%2Band%2BTricks)) |
|
||
| 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
|
||
|
||
````rsc
|
||
: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
|
||
|
||
```rsc
|
||
: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` |
|
||
|
||
---
|
||
|
||
|