Obsidean_VM/01-Documentation/Routers/Mikrotik - Network Redes/Scripting/Scripting Mikrotik.md

225 lines
9.1 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

***
[Scripting examples - RouterOS - MikroTik Documentation](https://help.mikrotik.com/docs/spaces/ROS/pages/139067404/Scripting+examples)
# MikroTik RouterOS Scripting  **Variables CheatSheet**
> **Updated:** 7 Aug 2025
> Tested on *RouterOS v7.15* (the syntax remains backwardcompatible 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* & *ipprefix*](#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. [MiniCookbook (readytouse snippets)](#8-mini-cookbook-ready-to-use-snippets)
9. [Quick Reference](#9-quick-reference)
---
## 1  Variable Declaration & Scope
| Keyword | Visibility | Lifetime | 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 | Interscript state, cached lookups, longrunning counters |
| `:local` | Current scope **only** (the curlybrace block, function, or interactive line that declared it) | Disappears as soon as execution leaves the block | Temporary loop counters, return values, throwaway buffers |
```rsc
:global buildDate "20250807";
{
: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, *redeclare* 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` | 64bit signed integer (hex input with `0x` allowed) |
| `bool` | `true` or `false` |
| `str` | UTF8 string |
| `ip` | IPv4 address (`10.0.0.1`) |
| `ipprefix` | IPv4 prefix (`10.0.0.0/24`) |
| `ip6` / `ip6prefix` | IPv6 address or prefix |
| `id` | Internal hex ID (always starts with `*`) |
| `time` | Absolute datetime 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] # -> ipprefix
: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* ↔︎ *ipprefix*).
Common helpers:
| Function | Converts … |
| ------------------- | -------------------- |
| `:tostr VALUE` | → `str` |
| `:tonum VALUE` | → `num` |
| `:toip VALUE` | → `ip` / `ipprefix` |
| `:toarray VALUE` | → `array` |
| `:tonothing` / `""` | → `nil` |
```rsc
# Compare an address coming from CLI (string) with one stored as ipprefix
:local needle 111.111.1.1/24
/ip address print where address=[:tostr $needle] ;# OK
```
Trying to compare `str` with `ipprefix` 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` & `ipprefix`
These types unlock bitwise operators, prefixmatching, 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 `ipprefix`, **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"
```
Multidimensional 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 `ipprefix`) | Cast with `:tostr` / `:toip` |
| Shadowing globals inside functions | Redeclare 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)) |
| Nonunique variable names (clashing with builtins) | Prefix your vars (e.g. `my_`, `ctx_`) |
---
## 8  MiniCookbook (readytouse 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 | Oneliner |
| -------------- | ---------------------- |
| 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` |
---