1Wprowadzenie do skryptowania w MikroTik RouterOS

Czym jest skrypt i dlaczego warto się tego nauczyć?

Zanim przejdziemy do szczegółów, odpowiedzmy na podstawowe pytanie: co to jest skrypt?

Wyobraź sobie, że codziennie rano musisz wykonywać te same czynności na routerze: sprawdzać status interfejsów, kasować stare logi, wysyłać raport e-mailem. Robienie tego ręcznie jest czasochłonne i narażone na błędy.

Skrypt to zestaw poleceń zapisany w pliku, który router wykonuje automatycznie. Zamiast klikać dziesiątki razy, piszesz instrukcje raz, a router wykonuje je za Ciebie.

Skrypty w RouterOS pozwalają na:

  • Automatyzację powtarzalnych zadań
  • Reagowanie na zdarzenia w sieci
  • Monitorowanie stanu urządzenia
  • Dynamiczną zmianę konfiguracji

Na tym wykładzie nauczysz się pisać własne skrypty krok po kroku, zaczynając od absolutnych podstaw.

Skrypty w MikroTik RouterOS stanowią nieodłączny element codziennej administracji sieciami opartymi na sprzęcie łotewskiego producenta. Możliwość automatyzacji powtarzalnych czynności, takich jak tworzenie kopii zapasowych, monitorowanie interfejsów czy dynamiczne zarządzanie regułami firewalla, pozwala zaoszczędzić wiele godzin ręcznej pracy i minimalizuje ryzyko popełnienia błędu. Język skryptowy RouterOS jest osadzony bezpośrednio w systemie operacyjnym urządzenia, co oznacza, że nie wymaga instalowania dodatkowego oprogramowania ani kompilatora. Wszystkie skrypty są przechowywane w pamięci routera i mogą być uruchamiane ręcznie, cyklicznie przez scheduler lub automatycznie w odpowiedzi na zdarzenia sieciowe.

W trakcie tego wykładu poznasz składnię języka skryptowego RouterOS, zaczniesz od definiowania zmiennych i używania operatorów, a skończysz na pisaniu zaawansowanych skryptów automatyzujących rzeczywiste zadania administracyjne. Wiedza zdobyta podczas kursu pozwoli Ci nie tylko usprawnić zarządzanie infrastrukturą sieciową, ale także lepiej zrozumieć wewnętrzne mechanizmy działania urządzeń MikroTik. Praktyczne przykłady i gotowe skrypty, które omówimy, będziesz mógł od razu wykorzystać w swoim środowisku produkcyjnym.

2RouterOS - system operacyjny routera

Czym jest MikroTik RouterOS?

RouterOS to specjalistyczny system operacyjny stworzony przez łotewską firmę MikroTik. Jest on instalowany na urządzeniach sieciowych tej firmy, takich jak routery, przełączniki, punkty dostępowe i firewalle.

RouterOS bazuje na jądrze Linux, ale ma swój własny interfejs zarządzania i wbudowany język skryptowy.

Jak można zarządzać RouterOS?

Istnieje kilka sposobów komunikacji z routerem:

  • WinBox - aplikacja z graficznym interfejsem (tylko Windows)
  • WebFig - zarządzanie przez przeglądarkę internetową
  • SSH/Telnet - dostęp przez wiersz poleceń (CLI)
  • Konsola (console) - bezpośrednio na urządzeniu

W tym wykładzie skupimy się na wierszu poleceń (CLI), ponieważ właśnie tam działa język skryptowy.

RouterOS to zaawansowany system operacyjny typu embedded, który pomimo swoich niewielkich rozmiarów oferuje funkcjonalność porównywalną z dedykowanymi rozwiązaniami korporacyjnymi. System oparty na jądrze Linux został gruntownie zmodyfikowany przez inżynierów MikroTik, aby zapewnić optymalną wydajność na architekturze MIPS, ARM i x86. Dzięki wbudowanemu językowi skryptowemu oraz rozbudowanemu interfejsowi CLI możliwe jest precyzyjne sterowanie każdym aspektem pracy urządzenia, od prostego przekazywania pakietów po złożone polityki jakości usług.

Administratorzy sieci mają do wyboru kilka metod zarządzania RouterOS, z których każda sprawdza się w innych scenariuszach. WinBox oferuje bogaty interfejs graficzny działający wyłącznie w systemie Windows, podczas gdy WebFig udostępnia podobne możliwości przez przeglądarkę. Dostęp przez SSH oraz konsola lokalna pozwalają natomiast na pełną kontrolę nad urządzeniem z poziomu terminala, co jest szczególnie cenne przy automatyzacji i skryptowaniu. Niezależnie od wybranej metody, podstawą efektywnej pracy pozostaje znajomość hierarchicznej struktury poleceń RouterOS.

3Jak połączyć się z routerem przez SSH

Nawiązywanie połączenia z routerem

Aby pisać skrypty, musisz najpierw połączyć się z routerem. Najczęściej używaną metodą jest SSH (Secure Shell).

W Windowsie możesz użyć:

  • PuTTY - darmowy klient SSH
  • Windows Terminal - wbudowany w Windows 10/11
  • WinBox - ma wbudowany terminal

Przykładowe połączenie:

W PuTTY wpisz adres IP routera (domyślnie 192.168.88.1), wybierz port 22 (SSH) i kliknij Connect.

Zaloguj się jako admin (domyślna nazwa użytkownika, bez hasła w fabrycznych ustawieniach).

Po zalogowaniu zobaczysz znak zachęty:

[admin@MikroTik] >

To oznacza, że jesteś w trybie poleceń RouterOS i możesz zacząć wpisywać komendy lub skrypty.

Nawiązanie połączenia z routerem MikroTik za pomocą protokołu SSH jest podstawową umiejętnością każdego administratora sieci. Domyślne ustawienia fabryczne routera zakładają adres IP 192.168.88.1 na interfejsie ether1 oraz nazwę użytkownika admin bez hasła, co umożliwia szybki pierwszy dostęp po podłączeniu komputera do tego samego interfejsu. W środowisku Windows najwygodniejszym narzędziem jest PuTTY, który oferuje bogate możliwości konfiguracji sesji SSH, w tym tunelowanie portów i zapisywanie profili połączeń. Windows Terminal stanowi nowocześniejszą alternatywę z obsługą zakładek i przezroczystości.

Po pomyślnym zalogowaniu się do routera użytkownik widzi znak zachęty w formacie `[admin@nazwa_routera] >`, który informuje o bieżącej nazwie użytkownika, identyfikatorze urządzenia oraz trybie pracy. W tym momencie można rozpocząć wpisywanie poleceń konfiguracyjnych lub skryptowych. Dla bezpieczeństwa warto natychmiast po pierwszym logowaniu zmienić domyślne hasło administratora, skonfigurować interfejsy sieciowe oraz wyłączyć nieużywane usługi zarządzania, takie jak telnet czy WinBox na interfejsach zewnętrznych.

4Struktura poleceń w RouterOS

Dwa typy poleceń

W RouterOS rozróżniamy dwa rodzaje poleceń:

  • Polecenia konfiguracyjne (ścieżki) - zaczynają się od ukośnika /
    Przykład: /ip address add address=192.168.1.1/24 interface=ether1
    Te polecenia odzwierciedlają hierarchię menu w RouterOS.
  • Polecenia skryptowe - zaczynają się od dwukropka :
    Przykład: :log info "Hello"
    Te polecenia są wbudowane w język skryptowy (pętle, warunki, zmienne).

Hierarchia menu

RouterOS ma strukturę drzewa. Aby przejść do sekcji IP, wpisz /ip. Aby przejść dalej, wpisz /ip address. Aby wyświetlić listę adresów, wpisz print.

Pełna składnia: /sciezka polecenie parametr=wartosc

Struktura poleceń w RouterOS opiera się na hierarchicznym modelu menu, który przypomina system plików w systemach Unix. Każdy element konfiguracji znajduje się w odpowiedniej ścieżce, na przykład konfiguracja adresów IP dostępna jest pod ścieżką `/ip address`. Polecenia konfiguracyjne poprzedzone ukośnikiem pozwalają na dodawanie, usuwanie i modyfikowanie wpisów w poszczególnych sekcjach. Z kolei polecenia skryptowe poprzedzone dwukropkiem, takie jak `:local`, `:if` czy `:foreach`, stanowią integralną część języka programowania wbudowanego w RouterOS.

Zrozumienie hierarchii menu oraz umiejętność rozróżniania poleceń konfiguracyjnych od skryptowych to klucz do efektywnego pisania skryptów. Polecenia skryptowe można używać zarówno w terminalu interaktywnym, jak i w zapisanych skryptach, natomiast polecenia konfiguracyjne są wykonywane w kontekście bieżącego menu lub ścieżki absolutnej. W praktyce większość skryptów łączy oba typy poleceń, tworząc spójną całość, która najpierw przygotowuje dane za pomocą konstrukcji językowych, a następnie modyfikuje konfigurację za pomocą poleceń systemowych.

5Nasz pierwszy skrypt

Jak wygląda najprostszy skrypt?

Zacznijmy od czegoś bardzo prostego. Najprostszy skrypt może wyglądać tak:

:put "Witaj, świecie!"

To polecenie wyświetla tekst "Witaj, świecie!" w konsoli.

Jak uruchomić skrypt?

Możesz wpisać go bezpośrednio w terminalu i nacisnąć Enter. Lub zapisać go na stałe:

  1. Wejdź do menu skryptów: /system script
  2. Dodaj nowy skrypt: add name=witaj source={:put "Witaj, świecie!"}
  3. Uruchom go: run witaj

Uwaga o nawiasach klamrowych

Jeśli skrypt ma więcej niż jedno polecenie, musisz umieścić je w nawiasach klamrowych { }.

Pierwszy skrypt w RouterOS to tradycyjny program wyświetlający tekst powitalny, który pozwala zapoznać się ze składnią i sposobem uruchamiania kodu. Komenda `:put "Witaj, świecie!"` wypisuje podany tekst w oknie konsoli i jest najprostszym przykładem działania interpretera języka skryptowego. Aby skrypt był przechowywany na stałe w systemie, należy dodać go do repozytorium za pomocą polecenia `/system script add name=witaj source={:put "Witaj, świecie!"}`, a następnie uruchomić przez `/system script run witaj`.

Nawiasy klamrowe pełnią w RouterOS kluczową rolę, ponieważ wyznaczają bloki kodu składające się z wielu poleceń. Pojedyncze polecenie może być podane bez nawiasów, ale przy dwóch lub więcej instrukcjach umieszczenie ich w `{}` jest obowiązkowe. Ta zasada dotyczy wszystkich konstrukcji językowych, w tym pętli, warunków i bloków `:do...on-error`. Przechowywanie skryptów w repozytorium umożliwia ich późniejsze wielokrotne uruchamianie, edycję oraz przypisanie do harmonogramu zadań.

6Repozytorium skryptów

Gdzie router przechowuje skrypty?

Wszystkie zapisane skrypty znajdziesz w menu /system script. To miejsce nazywamy repozytorium skryptów.

Podstawowe operacje w repozytorium:

  • /system script print - wyświetla listę wszystkich skryptów
  • /system script add name=moj_skrypt source={kod} - dodaje nowy skrypt
  • /system script run moj_skrypt - uruchamia skrypt
  • /system script remove moj_skrypt - usuwa skrypt
  • /system script edit moj_skrypt source - edytuje skrypt (otwiera edytor)

Dobre praktyki

Nadawaj skryptom opisowe nazwy (np. backup-konfiguracji, sprawdz-dns), aby łatwo było je znaleźć później. Dodawaj też komentarze wyjaśniające, co dany skrypt robi.

Repozytorium skryptów w RouterOS pełni funkcję centralnego magazynu kodu, w którym wszystkie skrypty są przechowywane i zarządzane za pomocą poleceń w ścieżce `/system script`. Najczęściej używane operacje to przeglądanie listy skryptów za pomocą `print`, dodawanie nowego skryptu przez `add` oraz uruchamianie istniejącego przez `run`. Każdy skrypt w repozytorium posiada unikalną nazwę, opcjonalny komentarz oraz zestaw uprawnień (policy), które określają, do jakich zasobów systemu skrypt ma dostęp podczas wykonywania.

Nadawanie skryptom opisowych, zrozumiałych nazw to dobra praktyka, która znacznie ułatwia zarządzanie większą liczbą skryptów na jednym urządzeniu. Zamiast nazwy typu `skrypt1` lepiej użyć `backup-konfiguracji` lub `sprawdz-dns`, co od razu informuje o przeznaczeniu danego kodu. Edycja skryptu odbywa się za pomocą polecenia `edit`, które otwiera wbudowany edytor tekstowy, natomiast usunięcie skryptu wykonuje komenda `remove`. Warto regularnie przeglądać repozytorium i usuwać nieużywane skrypty, aby utrzymać porządek w konfiguracji routera.

7Automatyczne uruchamianie skryptów - Scheduler

Co to jest Scheduler?

Scheduler (harmonogram) to narzędzie w RouterOS, które pozwala uruchamiać skrypty automatycznie o określonych porach lub w regularnych odstępach czasu.

Przykładowe zastosowania:

  • Tworzenie backupu codziennie o 3:00 w nocy
  • Sprawdzanie dostępności hostów co 5 minut
  • Czyszczenie starych logów co godzinę

Jak dodać zadanie do harmonogramu?

/system scheduler add name=daily-backup interval=1d on-event=backup-konfiguracji

To polecenie tworzy zadanie o nazwie "daily-backup", które uruchomi skrypt "backup-konfiguracji" raz dziennie (interval=1d oznacza 1 dzień).

Jednostki czasu:

  • s - sekundy, m - minuty, h - godziny, d - dni

Scheduler w RouterOS to narzędzie do cyklicznego uruchamiania skryptów o określonych porach lub interwałach czasowych, pełniące funkcję analogiczną do Cron w systemach Unix. Konfiguracja zadania polega na podaniu nazwy, interwału czasowego oraz nazwy skryptu, który ma zostać wykonany. Jednostki czasu obejmują sekundy (s), minuty (m), godziny (h) oraz dni (d), co pozwala na precyzyjne dostosowanie częstotliwości uruchamiania do konkretnych potrzeb administracyjnych.

Praktyczne zastosowania schedulera są bardzo różnorodne i obejmują między innymi codzienne tworzenie kopii zapasowych o stałej porze, monitorowanie dostępności hostów co kilka minut czy cykliczne czyszczenie starych logów. W polu `start-time` można określić konkretną godzinę rozpoczęcia pierwszego zadania, a parametr `interval` definiuje odstęp między kolejnymi uruchomieniami. Scheduler uruchamia skrypty w tle, co oznacza, że ich działanie nie blokuje interaktywnej sesji terminala i mogą one wykonywać się niezależnie od bieżących działań administratora.

8Komentarze w skryptach

Po co nam komentarze?

Komentarz to tekst w skrypcie, który jest ignorowany podczas wykonania. Służy do dokumentowania i wyjaśniania kodu.

Dobre komentarze sprawiają, że skrypt jest zrozumiały dla innych (i dla Ciebie, gdy wrócisz do niego po miesiącu).

Jak pisać komentarze w RouterOS?

Linie zaczynające się od znaku # są traktowane jako komentarze:

# To jest komentarz - router to zignoruje

Możesz też umieszczać komentarze na końcu linii:

:local licznik 0 # Inicjalizacja licznika

Przykład użycia komentarzy:

# ==============================================
# Skrypt: sprawdz-interfejs.rsc
# Autor: Jan Kowalski
# Data: 2024-01-15
# Opis: Sprawdza status interfejsu ether1
# ==============================================

# Pobierz nazwę interfejsu do sprawdzenia
:local interfejs "ether1"

# Sprawdź, czy interfejs działa
:local status [/interface get [find name=$interfejs] running]

# Jeśli działa, zapisz informację w logu
:if ($status = true) do={
    :log info ("Interfejs " . $interfejs . " jest aktywny.")
}

Komentarze w skryptach RouterOS są nieodzownym elementem profesjonalnego kodu, który ułatwia zrozumienie intencji autora oraz przyspiesza wprowadzanie zmian w przyszłości. Znak `#` na początku linii powoduje, że cała jej zawartość jest ignorowana przez interpreter, co pozwala na umieszczanie opisów, ostrzeżeń i informacji o autorze bez wpływu na działanie skryptu. Komentarze można również umieszczać na końcu linii z kodem, co jest przydatne przy wyjaśnianiu konkretnych instrukcji bez rozbijania struktury wizualnej skryptu.

Dobrą praktyką jest rozpoczynanie każdego pliku skryptu od nagłówka zawierającego nazwę, autora, datę utworzenia i krótki opis przeznaczenia. W trakcie pisania kodu warto komentować przede wszystkim dlaczego dana operacja jest wykonywana, a nie co robi, ponieważ sama składnia instrukcji powinna być czytelna dla osoby znającej język. Komentarze przydają się również tymczasowo podczas debugowania, gdy wyłączamy fragmenty kodu w celu zlokalizowania źródła problemu, oznaczając je znakiem `#` na początku linii.

9Zmienne - podstawy

Co to jest zmienna?

Zmienna to jak pudełko z etykietą, w którym możesz przechowywać dane. Pudełko ma nazwę (etykietę), a w środku może być dowolna wartość.

Wyobraź sobie, że chcesz zapisać adres IP routera. Zamiast wpisywać go wielokrotnie, możesz stworzyć zmienną:

:local mojIP "192.168.1.1"

Teraz zamiast wpisywać "192.168.1.1", możesz używać nazwy $mojIP.

Rodzaje zmiennych:

  • Zmienne lokalne (:local) - istnieją tylko podczas jednego uruchomienia skryptu
  • Zmienne globalne (:global) - istnieją w całym systemie, nawet między uruchomieniami

Omówimy je szczegółowo w kolejnych slajdach.

Zmienne w języku skryptowym RouterOS stanowią podstawowy mechanizm przechowywania i manipulowania danymi w trakcie wykonywania skryptu. Każda zmienna posiada nazwę, typ oraz wartość, a dostęp do niej odbywa się przez poprzedzenie nazwy znakiem dolara `$`. RouterOS rozróżnia dwa rodzaje zmiennych: lokalne deklarowane słowem kluczowym `:local`, które istnieją tylko podczas jednego uruchomienia skryptu, oraz globalne deklarowane przez `:global`, których wartość jest zachowywana w systemie między kolejnymi uruchomieniami.

Zmienne lokalne są zalecane w codziennym użyciu, ponieważ nie powodują efektów ubocznych w postaci niezamierzonego nadpisania danych używanych przez inne skrypty. Deklaracja zmiennej może zawierać wartość początkową lub pozostawiać zmienną niezainicjowaną z typem `nil`. Wartość zmiennej modyfikuje się za pomocą polecenia `:set`, a w wyrażeniach odwołanie do zmiennej wymaga znaku `$`. W przeciwieństwie do wielu języków programowania, w RouterOS nie ma rozróżnienia między deklaracją a przypisaniem, co upraszcza składnię.

10Zmienne lokalne

Zmienne lokalne - definicja

Zmienna lokalna (:local) istnieje tylko w jednym uruchomieniu skryptu. Po zakończeniu skryptu znika.

Jest idealna do przechowywania tymczasowych danych, wyników pośrednich, liczników w pętlach.

Składnia:

:local nazwa zmiennej wartość

Możesz też stworzyć zmienną bez wartości (będzie miała specjalny typ "nil"):

:local moja_zmienna

Przykład użycia:

# Deklaracja zmiennej lokalnej z wartoscia tekstowa
:local imie "Anna"

# Deklaracja zmiennej lokalnej z liczba
:local wiek 25

# Deklaracja zmiennej lokalnej bez wartości
:local tymczasowyWynik

# Użycie zmiennej - poprzedź nazwę znakiem $
:put ("Mam na imię " . $imie)
:put ("Mam " . $wiek . " lat")

# Możesz zmienić wartość zmiennej
:set wiek 26
:put ("Teraz mam " . $wiek . " lat")

Zmienne lokalne w RouterOS są przeznaczone do przechowywania danych tymczasowych, które są potrzebne wyłącznie w kontekście bieżącego uruchomienia skryptu. Deklaracja zmiennej lokalnej odbywa się za pomocą polecenia `:local nazwa wartość`, przy czym podanie wartości początkowej jest opcjonalne. Zmienna bez wartości przyjmuje specjalny typ `nil`, który oznacza brak danych i może być sprawdzany za pomocą operatora `[:typeof]`. Zmienne lokalne są automatycznie usuwane z pamięci po zakończeniu działania skryptu, co zapobiega wyciekom pamięci i konfliktom nazw.

W praktyce zmienne lokalne są używane do przechowywania wyników pośrednich obliczeń, wartości liczników w pętlach, tymczasowych danych z odczytu konfiguracji oraz wszystkich innych informacji, które nie muszą być dostępne po zakończeniu skryptu. Zakres widoczności zmiennej lokalnej ogranicza się do bloku kodu, w którym została zadeklarowana, co oznacza, że zmienna zdefiniowana wewnątrz nawiasów klamrowych nie jest dostępna na zewnątrz. Ta cecha pozwala na bezpieczne używanie tych samych nazw zmiennych w różnych częściach skryptu bez ryzyka konfliktu.

11Zmienne globalne

Zmienne globalne - definicja

Zmienna globalna (:global) istnieje w całym systemie RouterOS i zachowuje swoją wartość nawet po zakończeniu skryptu. Znika dopiero po restarcie routera lub po jej usunięciu.

Jest idealna do przechowywania stanu, który musi być współdzielony między różnymi skryptami.

Składnia:

:global nazwa zmiennej wartość

Przykład zastosowania:

Załóżmy, że masz skrypt monitorujący host. Chcesz wiedzieć, czy host był ostatnio online czy offline. Używasz zmiennej globalnej, aby zapamiętać poprzedni stan.

# --- Skrypt 1: Sprawdza stan i zapisuje go ---

# Deklaracja zmiennej globalnej (jeśli jeszcze nie istnieje)
:global poprzedniStatus

# Pobierz aktualny status
:local aktualnyStatus [/ping 8.8.8.8 count=1]

# Sprawdź, czy status się zmienił
:if ($aktualnyStatus != $poprzedniStatus) do={
    :log info ("Status zmienil sie z " . $poprzedniStatus . " na " . $aktualnyStatus)
    
    # Zapisz nowy status - będzie dostępny następnym razem
    :set poprzedniStatus $aktualnyStatus
}

Zmienne globalne w RouterOS różnią się od lokalnych przede wszystkim czasem życia oraz zakresem widoczności. Po zadeklarowaniu zmiennej globalnej za pomocą `:global nazwa wartość` jej wartość pozostaje dostępna w systemie nawet po zakończeniu skryptu, aż do restartu urządzenia lub ręcznego usunięcia. Dzięki temu zmienne globalne doskonale nadają się do przechowywania stanu między uruchomieniami, takiego jak poprzedni status monitorowanego hosta czy licznik wykonanych operacji.

Należy jednak zachować ostrożność przy używaniu zmiennych globalnych, ponieważ niekontrolowane ich rozrastanie może prowadzić do nieprzewidywalnych zachowań i trudnych do zdiagnozowania błędów. Przed użyciem zmiennej globalnej warto sprawdzić, czy w ogóle istnieje, za pomocą `:if ([:typeof $zmienna] = "nil")`, aby uniknąć błędów wykonania. Zmienne globalne doskonale sprawdzają się w roli wspólnego stanu dla kilku skryptów współpracujących ze sobą, realizujących na przykład mechanizm failover między dwoma łączami internetowymi.

12Zmienne - dobre praktyki i pułapki

Na co uważać przy pracy ze zmiennymi?

  • Używaj unikalnych nazw - jeśli masz zmienną lokalną i globalną o tej samej nazwie, lokalna "przesłania" globalną w swoim zakresie.
  • Sprawdzaj, czy zmienna istnieje - przed użyciem zmiennej globalnej warto sprawdzić, czy została zdefiniowana.
  • Uważaj na zasięg zmiennych - zmienna zdefiniowana wewnątrz nawiasów klamrowych ({}) istnieje tylko tam.

Jak sprawdzić typ zmiennej?

Użyj polecenia :typeof:

:local mojTekst "Hello"
:local mojaLiczba 42
:local mojBool true

:put ("Typ mojTekst: " . [:typeof $mojTekst])
:put ("Typ mojaLiczba: " . [:typeof $mojaLiczba])
:put ("Typ mojBool: " . [:typeof $mojBool])

# Wynik:
# Typ mojTekst: str
# Typ mojaLiczba: num
# Typ mojBool: bool

Stosowanie dobrych praktyk przy pracy ze zmiennymi w RouterOS pozwala uniknąć wielu typowych błędów popełnianych przez początkujących administratorów. Najważniejsza zasada to używanie jednoznacznych i opisowych nazw zmiennych, które odzwierciedlają przechowywaną wartość na przykład `licznikProbow` zamiast `x`. Należy również pamiętać o różnicach między zmiennymi lokalnymi a globalnymi, ponieważ zmienna lokalna o tej samej nazwie co globalna przesłania tę drugą w swoim zakresie, co może prowadzić do subtelnych błędów logicznych.

Sprawdzanie typu zmiennej za pomocą `:typeof` jest szczególnie przydatne podczas debugowania i walidacji danych wejściowych. W przypadku zmiennych globalnych warto przed pierwszym użyciem w nowej sesji sprawdzić, czy zostały już zainicjalizowane. Pisząc skrypty przeznaczone do współdzielenia z zespołem, dobrze jest stosować spójny styl nazewnictwa, na przykład poprzedzać zmienne globalne przedrostkiem `cfg` dla wartości konfiguracyjnych. Systematyczne stosowanie tych reguł znacząco podnosi jakość i niezawodność tworzonego kodu.

13Typy danych - podstawowe

Typy danych w RouterOS

RouterOS automatycznie rozpoznaje typ wartości, którą przypisujesz do zmiennej. Oto najważniejsze typy:

  • str (string) - ciąg znaków, np. "Hello World", "ether1"
    Zapis: :local tekst "jakiś tekst"
  • num (number) - liczba (całkowita lub zmiennoprzecinkowa)
    Zapis: :local liczba 42 lub :local pi 3.14
  • ip - adres IP (wersja 4 lub 6)
    Zapis: :local adres 192.168.1.1
  • bool (boolean) - wartość logiczna
    Zapis: :local prawda true lub :local falsz false

RouterOS sam rozpoznaje typ na podstawie wartości - nie musisz go określać jawnie.

RouterOS automatycznie rozpoznaje typ wartości przypisywanej do zmiennej, co oznacza, że administrator nie musi jawnie określać, czy zmienna przechowuje tekst, liczbę czy adres IP. Typ `str` służy do przechowywania ciągów znaków i jest najczęściej używany do komunikatów, nazw interfejsów oraz wszelkich danych tekstowych. Typ `num` reprezentuje liczby całkowite i zmiennoprzecinkowe, na przykład `42` lub `3.14`, i pozwala na wykonywanie operacji arytmetycznych. Typ `ip` obsługuje adresy IPv4 oraz IPv6, co jest szczególnie przydatne w skryptach związanych z konfiguracją sieci.

Typ `bool` przyjmuje jedną z dwóch wartości logicznych `true` lub `false`, używanych głównie w instrukcjach warunkowych i pętlach. RouterOS samodzielnie rozpoznaje właściwy typ na podstawie składni wartości, co w większości przypadków działa bezbłędnie. W sytuacjach wątpliwych można jawnie sprawdzić typ za pomocą `:typeof zmienna`, które zwraca nazwę typu jako tekst. Takie automatyczne wnioskowanie typów znacząco przyspiesza pisanie skryptów, jednocześnie wymagając od autora świadomości, że wartość musi być zapisana w odpowiednim formacie.

14Typy danych - zaawansowane

Inne przydatne typy danych

  • ip-prefix - adres IP z maską podsieci
    Przykład: 192.168.1.0/24
  • time - przedział czasu
    Przykład: 1d2h3m4s (1 dzień, 2 godziny, 3 minuty, 4 sekundy)
    Przydatne przy ustawianiu timeoutów i interwałów.
  • array - tablica (lista wartości)
    Przykład: {1, 2, 3, "tekst", 5.5}
    Omówimy ją szczegółowo w dalszej części.
  • nil - specjalny typ oznaczający "brak wartości"
    Zmienna bez przypisanej wartości ma właśnie ten typ.

Jak sprawdzić typ?

Użyj polecenia :typeof zmienna:

:put [:typeof 192.168.1.1] - zwróci "ip"

:put [:typeof "tekst"] - zwróci "str"

Oprócz podstawowych typów danych RouterOS oferuje bardziej zaawansowane typy przydatne w kontekście administracji sieciowej. Typ `ip-prefix` łączy adres IP z maską podsieci, na przykład `192.168.1.0/24`, i jest używany przy definiowaniu sieci w konfiguracji interfejsów czy tras statycznych. Typ `time` wyraża przedziały czasu w formacie `1d2h3m4s` i znajduje zastosowanie przy ustawianiu timeoutów połączeń, interwałów schedulera oraz ważności wpisów na listach adresowych.

Typ `array` (tablica) pozwala na przechowywanie wielu wartości pod jedną nazwą, co jest niezwykle przydatne przy grupowaniu powiązanych danych. Tablicę tworzy się za pomocą nawiasów klamrowych z elementami oddzielonymi przecinkami, na przykład `{1, 2, 3, "tekst", 5.5}`. Typ `nil` oznacza całkowity brak wartości i jest domyślnym typem zmiennej niezainicjalizowanej. Zrozumienie dostępnych typów danych i ich charakterystyk jest kluczowe dla pisania poprawnych i wydajnych skryptów.

15Operatory arytmetyczne

Działania matematyczne w skryptach

RouterOS pozwala na wykonywanie podstawowych operacji matematycznych:

  • + - dodawanie
  • - - odejmowanie
  • * - mnożenie
  • / - dzielenie

Operacje umieszczamy w nawiasach okrągłych, np. ($a + $b).

Przykłady:

:local a 10
:local b 3

:put ("a + b = " . ($a + $b))     # 13
:put ("a - b = " . ($a - $b))     # 7
:put ("a * b = " . ($a * $b))    # 30
:put ("a / b = " . ($a / $b))    # 3 (dzielenie całkowite)

# Operacje z mieszanymi typami
:local x 5
:local y 2.5
:put ("x + y = " . ($x + $y))    # 7.5

# Modyfikacja zmiennej
:set a ($a + 5)
:put ("a po dodaniu 5 = " . $a)  # 15

Operatory arytmetyczne w języku skryptowym RouterOS umożliwiają wykonywanie podstawowych działań matematycznych, takich jak dodawanie, odejmowanie, mnożenie i dzielenie. Wszystkie operacje arytmetyczne wymagają umieszczenia wyrażenia w nawiasach okrągłych, na przykład `($a + $b)`, co odróżnia składnię RouterOS od wielu innych języków programowania. Dzielenie dwóch liczb całkowitych zwraca wynik całkowity bez reszty, co jest zgodne z działaniem dzielenia całkowitoliczbowego znanego z języków niskiego poziomu.

Operatory arytmetyczne znajdują praktyczne zastosowanie w wielu typowych zadaniach administracyjnych, takich jak obliczanie procentowego wykorzystania pamięci RAM, przeliczanie jednostek, generowanie sekwencji numerów czy modyfikowanie wartości liczników. Modyfikacja zmiennej przez dodanie do niej wartości może być wykonana za pomocą wyrażenia `:set a ($a + 5)`, co zwiększa wartość zmiennej `a` o 5. W pętlach często używa się inkrementacji licznika poprzez `:set i ($i + 1)`, co umożliwia odliczanie i kontrolowanie liczby iteracji.

16Operatory porównania

Porównywanie wartości

Operatory porównania służą do sprawdzania relacji między wartościami. Używamy ich głównie w instrukcjach warunkowych.

  • = - równy
  • > - większy niż
  • < - mniejszy niż
  • >= - większy lub równy
  • <= - mniejszy lub równy
  • != lub <> - nierówny

Ważne: Do sprawdzenia "nierówności" zalecane jest użycie negacji: :if (!($a = $b))

Przykłady:

:local wiek 20
:local granica 18

:if ($wiek >= $granica) do={
    :put "Osoba jest pełnoletnia"
} else={
    :put "Osoba jest niepełnoletnia"
}

# Sprawdzenie nierówności (dwie równoważne formy)
:local imie "Anna"
:if ($imie != "Jan") do={
    :put "To nie jest Jan"
}

# Lub z negacją
:if (!($imie = "Jan")) do={
    :put "To nie jest Jan"
}

Operatory porównania w RouterOS służą do sprawdzania relacji między dwiema wartościami i zwracają wynik logiczny true lub false. Operator `=` sprawdza równość, `!=` nierówność, a operatory `>`, `<`, `>=`, `<=` porównują wielkość liczb i innych wartości uporządkowanych. W przeciwieństwie do wielu języków programowania, RouterOS używa pojedynczego znaku `=` zarówno do przypisania, jak i do porównania, co na początku może być mylące dla programistów przyzwyczajonych do składni z podwójnym znakiem `==`.

Operator nierówności `!=` jest równoważny, ale w społeczności RouterOS często zaleca się używanie konstrukcji z negacją `:if (!($a = $b))`, która jest bardziej czytelna i zgodna z ogólną filozofią języka. Operatory porównania są najczęściej używane w instrukcjach warunkowych `:if`, gdzie decydują o wyborze ścieżki wykonania kodu. W praktyce administracyjnej porównania znajdują zastosowanie przy sprawdzaniu statusu interfejsów, weryfikacji wartości zmiennych i podejmowaniu decyzji konfiguracyjnych na podstawie bieżącego stanu urządzenia.

17Operatory logiczne

Łączenie warunków

Operatory logiczne pozwalają łączyć wiele warunków w jednym wyrażeniu:

  • and - oba warunki muszą być prawdziwe (koniunkcja)
  • or - przynajmniej jeden warunek musi być prawdziwy (alternatywa)
  • not - zaprzeczenie warunku

Tabela prawdy:

  • true and true = true
  • true and false = false
  • true or false = true
  • false or false = false
  • not true = false
:local wiek 25
:local maPrawoJazdy true
:local jestTrzeźwy true

# Sprawdzenie, czy osoba może prowadzić
:if ($wiek >= 18 and $maPrawoJazdy = true and $jestTrzeźwy = true) do={
    :put "Może prowadzić samochód"
} else={
    :put "Nie może prowadzić samochodu"
}

# Przykład z OR - przynajmniej jedno musi być spełnione
:local maKlucz false
:local znaKod true

:if ($maKlucz = true or $znaKod = true) do={
    :put "Można wejść do pomieszczenia"
}

Operatory logiczne w RouterOS pozwalają na łączenie wielu warunków w jedno złożone wyrażenie, co jest niezbędne przy budowaniu zaawansowanej logiki decyzyjnej. Operator `and` zwraca true tylko wtedy, gdy wszystkie połączone warunki są prawdziwe, natomiast `or` zwraca true, gdy przynajmniej jeden z warunków jest spełniony. Operator `not` odwraca wartość logiczną warunku, zamieniając true na false i odwrotnie. Operatory logiczne mogą być dowolnie zagnieżdżane, co pozwala na tworzenie bardzo precyzyjnych kryteriów decyzyjnych.

W praktyce operatory logiczne są używane we wszystkich sytuacjach, gdzie pojedynczy warunek nie wystarczy do podjęcia decyzji. Przykładowo sprawdzenie, czy użytkownik może prowadzić samochód, wymaga jednoczesnego spełnienia warunku odpowiedniego wieku, posiadania prawa jazdy oraz bycia trzeźwym, co realizuje się za pomocą połączenia operatorów `and`. Operator `or` przydaje się z kolei w sytuacjach, gdy dostęp do zasobu jest możliwy przez kilka alternatywnych ścieżek, na przykład posiadanie klucza lub znajomość kodu dostępu. Zrozumienie operatorów logicznych jest fundamentem budowania złożonej logiki w skryptach.

18Łączenie tekstów (konkatenacja)

Dodawanie tekstów do siebie

Aby połączyć (skleić) dwa teksty, używamy operatora kropki (.). Operacja ta nazywa się konkatenacją.

Jest to bardzo przydatne, gdy chcesz zbudować dłuższy komunikat złożony z tekstu stałego i wartości zmiennych.

Składnia:

"tekst stały " . $zmienna . " kolejny tekst"

Przykłady:

:local imie "Jan"
:local nazwisko "Kowalski"

# Proste polaczenie dwoch tekstow
:local pelneImie ($imie . " " . $nazwisko)
:put $pelneImie  # Jan Kowalski

# Budowanie komunikatu
:local interfejs "ether1"
:local status "aktywny"
:put ("Interfejs " . $interfejs . " jest " . $status)
# Wynik: Interfejs ether1 jest aktywny

# Laczenie z liczbami
:local liczba 42
:put ("Odpowiedź to: " . $liczba)
# Wynik: Odpowiedź to: 42

# Uwaga: używaj nawiasów () przy zmiennych w konkatenacji
:put "Wynik: " . $liczba   # Działa
:put "Wynik: $liczba"     # To jest zwykły tekst, nie podstawi zmiennej!

Konkatenacja tekstów za pomocą operatora kropki `.` jest w RouterOS podstawowym mechanizmem łączenia stałych tekstowych z wartościami zmiennych w celu tworzenia czytelnych komunikatów. Operator ten działa na wszystkich typach danych, automatycznie konwertując wartości liczbowe i inne typy na tekst przed połączeniem. W praktyce konkatenacja jest używana przy budowaniu komunikatów logów, przygotowywaniu URL do żądań HTTP, formatowaniu raportów oraz wszędzie tam, gdzie potrzebny jest dynamiczny ciąg znaków składający się z kilku elementów.

Ważną zasadą przy konkatenacji w RouterOS jest konieczność używania nawiasów, gdy łączymy wyrażenia skomplikowane. Na przykład `:put ("Wynik: " . $liczba)` zadziała poprawnie, ale `:put "Wynik: " . $liczba` zostanie zinterpretowane jako dwa osobne argumenty polecenia `:put`. Podstawienie zmiennej wewnątrz tekstu za pomocą składni `$zmienna` nie działa w RouterOS tak jak w PowerShell czy BASH, dlatego konieczne jest jawne użycie operatora `.`. Pomimo tego ograniczenia konkatenacja pozostaje elastycznym i niezawodnym narzędziem do budowania tekstów.

19Instrukcja warunkowa if - podstawy

Co to jest instrukcja warunkowa?

Instrukcja warunkowa pozwala na wykonanie różnych czynności w zależności od spełnienia warunku. To jak rozmowa z routerem: "JEŚLI (warunek) TO (zrób to) W PRZECIWNYM RAZIE (zrób tamto)".

Składnia:

:if (warunek) do={
    # kod do wykonania, gdy warunek jest prawdziwy
}

Blok else jest opcjonalny:

:if (warunek) do={
    # kod gdy prawda
} else={
    # kod gdy fałsz
}

Nawiasy klamrowe { } wyznaczają blok kodu. Nawiasy okrągłe ( ) zawierają warunek.

:local temperatura 22

:if ($temperatura > 25) do={
    :put "Jest goraco - wlacz klimatyzacje"
} else={
    :put "Temperatura jest OK"
}

# Prostszy przykład bez else
:if ($temperatura > 30) do={
    :log warning "Uwaga! Bardzo goraco!"
}

:put "Skrypt zakończony"

Instrukcja warunkowa `:if` jest fundamentem logiki decyzyjnej w języku skryptowym RouterOS i pozwala na wykonywanie różnych bloków kodu w zależności od spełnienia określonego warunku. Pełna składnia instrukcji to `:if (warunek) do={ kod } else={ kod }`, przy czym blok `else` jest opcjonalny i można go pominąć, gdy nie ma potrzeby wykonywania alternatywnego kodu. Warunek umieszczony w nawiasach okrągłych musi być wyrażeniem zwracającym wartość logiczną, a bloki kodu w nawiasach klamrowych mogą zawierać dowolną liczbę poleceń.

W codziennej pracy administratora instrukcja `:if` jest używana praktycznie w każdym skrypcie, od prostych sprawdzeń stanu interfejsów po złożone wielopoziomowe decyzje konfiguracyjne. Należy pamiętać o poprawnej składni, w szczególności o dwukropku przed `if` oraz słowie kluczowym `do=` przed blokiem kodu. Częstym błędem początkujących jest zapominanie o dwukropku lub używanie nieprawidłowej składni bloku else. Instrukcje `:if` można dowolnie zagnieżdżać, tworząc rozbudowane drzewa decyzyjne.

20Instrukcja if - praktyczne przykłady

Sprawdzanie statusu interfejsu

Jednym z najczęstszych zastosowań if jest sprawdzanie, czy interfejs sieciowy jest aktywny.

# Pobierz status interfejsu ether1
:local interfejs "ether1"
:local status [/interface get [find name=$interfejs] running]

:if ($status = true) do={
    :log info ("Interfejs " . $interfejs . " jest uruchomiony.")
} else={
    :log error ("Interfejs " . $interfejs . " jest wyłączony!")
}

# Sprawdzanie, czy zmienna ma wartość (nie jest nil)
:global mojaZmienna
:if ([:typeof $mojaZmienna] = "nil") do={
    :log info "Zmienna nie ma wartosci, ustawiam domyslna"
    :set mojaZmienna "wartość domyślna"
}

Praktyczne zastosowania instrukcji warunkowej `:if` w RouterOS są niezwykle różnorodne i obejmują większość typowych zadań administracyjnych. Najczęstszym przykładem jest sprawdzenie statusu interfejsu sieciowego przed podjęciem decyzji o zmianie konfiguracji lub wygenerowaniu alarmu. W tym celu pobiera się wartość właściwości `running` dla danego interfejsu za pomocą polecenia `/interface get` i porównuje z wartością `true`, co pozwala określić, czy interfejs jest aktywny, czy nie.

Innym powszechnym zastosowaniem jest sprawdzenie, czy zmienna globalna została zainicjalizowana przed jej użyciem. Warunek `:if ([:typeof $mojaZmienna] = "nil")` pozwala wykryć, czy zmienna ma wartość, czy jest pusta, i odpowiednio zareagować, na przykład ustawiając wartość domyślną. Tego typu zabezpieczenia są szczególnie ważne w skryptach uruchamianych przez scheduler, gdzie nie ma interaktywnego użytkownika, który mógłby zweryfikować poprawność danych. Instrukcja `:if` w połączeniu z odpowiednio skonstruowanymi warunkami stanowi podstawę niezawodnych skryptów administracyjnych.

21Zagnieżdżone instrukcje if

Wiele warunków jeden po drugim

Czasami potrzebujesz sprawdzić więcej niż jeden warunek. Możesz umieścić jedną instrukcję if wewnątrz drugiej - to nazywamy zagnieżdżaniem.

Uwaga: staraj się nie zagnieżdżać zbyt głęboko - kod staje się wtedy trudny do czytania.

:local wiek 17
:local maBilets true

:if ($wiek >= 18) do={
    :if ($maBilets = true) do={
        :put "Możesz obejrzeć film"
    } else={
        :put "Masz wiek, ale nie masz biletu"
    }
} else={
    :put "Nie masz wymaganego wieku"
}

# Lepsza alternatywa - użycie else if
:if ($wiek < 13) do={
    :put "Bilet dziecięcy"
} else if ($wiek < 18) do={
    :put "Bilet ulgowy"
} else={
    :put "Bilet normalny"
}

Zagnieżdżanie instrukcji `:if` pozwala na tworzenie rozbudowanych struktur decyzyjnych, w których jedna decyzja zależy od wyniku wcześniejszej. Mimo że zagnieżdżanie jest technicznie możliwe do dowolnej głębokości, w praktyce zaleca się ograniczanie do maksymalnie trzech poziomów, ponieważ kod staje się wówczas trudny do czytania i podatny na błędy logiczne. Alternatywą dla głębokiego zagnieżdżania jest zastosowanie konstrukcji `else if`, która umożliwia sprawdzenie kilku warunków na tym samym poziomie hierarchii.

Konstrukcja `else if` jest czytelniejsza i łatwiejsza w utrzymaniu niż seria zagnieżdżonych `:if`, szczególnie w przypadku, gdy mamy do czynienia z wyłącznymi przedziałami wartości. Przykładowo sprawdzenie przedziałów wiekowych dla biletów można zapisać jako serię warunków `:if ($wiek < 13) ... else if ($wiek < 18) ... else ...`, która jest znacznie czytelniejsza niż odpowiadające jej zagnieżdżenie. W profesjonalnych skryptach warto przed napisaniem kodu zaplanować logikę decyzyjną i wybrać najczytelniejszą formę jej implementacji.

22Pętla for

Wielokrotne wykonywanie operacji

Pętla pozwala wielokrotnie wykonać ten sam fragment kodu. Pętla for jest idealna, gdy znasz dokładną liczbę powtórzeń.

Składnia:

:for zmienna from=początek to=koniec step=krok do={
    # kod do wykonania
}
  • zmienna - nazwa zmiennej-licznika
  • from - wartość początkowa
  • to - wartość końcowa
  • step - o ile zwiększać licznik za każdym razem (domyślnie 1)
# Wypisz liczby od 1 do 5
:for i from=1 to=5 do={
    :put ("Licznik: " . $i)
}

# Wypisz liczby parzyste od 2 do 10
:for i from=2 to=10 step=2 do={
    :put ("Liczba parzysta: " . $i)
}

# Przykład: stwórz 3 reguły firewalla
:for i from=1 to=3 do={
    /ip firewall filter add chain=forward action=accept \
        comment=("Reguła testowa numer " . $i)
    :log info ("Utworzono regula numer " . $i)
}

Pętla `:for` w RouterOS służy do wielokrotnego wykonywania bloku kodu z licznikiem zmieniającym się od wartości początkowej do końcowej z określonym krokiem. Składnia `:for i from=1 to=10 step=2 do={ kod }` pozwala na precyzyjne kontrolowanie liczby iteracji oraz wartości licznika w każdej z nich. Parametr `step` jest opcjonalny i domyślnie wynosi 1, co oznacza, że licznik zwiększa się o jeden przy każdej iteracji. Pętla `:for` jest idealna, gdy znamy dokładną liczbę powtórzeń przed rozpoczęciem wykonywania pętli.

W administracji MikroTik pętla `:for` znajduje zastosowanie między innymi przy generowaniu sekwencji reguł firewalla, gdzie każda kolejna reguła ma inny numer lub komentarz. Przykładowo skrypt tworzący trzy reguły `for i from=1 to=3` z dynamicznym komentarzem zawierającym numer iteracji pozwala zaoszczędzić wiele ręcznego pisania. Pętla `:for` może być również używana do iteracji w dół poprzez ustawienie wartości początkowej większej od końcowej, co jest przydatne przy odliczaniu lub operacjach na stosach.

23Pętla foreach - wprowadzenie

Pętla foreach - najważniejsza pętla w RouterOS

foreach służy do przechodzenia przez elementy kolekcji (listy, tablicy) lub wyników poleceń. Jest to najczęściej używana pętla w skryptach RouterOS.

Składnia:

:foreach zmienna in=kolekcja do={
    # kod do wykonania dla każdego elementu
}

Za każdym razem zmienna przyjmuje wartość kolejnego elementu z kolekcji.

# Przyklad 1: Iteracja po liscie (tablicy)
:local mojaLista {1, 2, 3, 4, 5}

:foreach element in=$mojaLista do={
    :put ("Element: " . $element)
}

# Przykład 2: Iteracja po interfejsach
:foreach iface in=[/interface find] do={
    :local ifaceName [/interface get $iface name]
    :put ("Interfejs: " . $ifaceName)
}

Pętla `:foreach` jest najczęściej używaną pętlą w skryptach RouterOS i służy do iteracji po elementach kolekcji, takich jak tablice, listy identyfikatorów czy wyniki poleceń. Składnia `:foreach element in=$kolekcja do={ kod }` przechodzi przez każdy element kolekcji, przypisując go do zmiennej `element`, która jest dostępna wewnątrz bloku kodu. W przeciwieństwie do pętli `:for`, `:foreach` nie wymaga znajomości liczby elementów z góry i automatycznie dostosowuje się do rozmiaru kolekcji, co czyni ją bezpieczniejszą i wygodniejszą w większości przypadków.

W praktyce `:foreach` jest używana przede wszystkim do przetwarzania wyników polecenia `find`, które zwraca listę wewnętrznych identyfikatorów elementów spełniających zadane kryteria. Typowy wzorzec polega na znalezieniu interesujących nas elementów za pomocą `find`, a następnie przetworzeniu każdego z nich w pętli `:foreach`, gdzie dla każdego identyfikatora pobieramy szczegółowe dane za pomocą `get` lub modyfikujemy właściwości przez `set`. Ten wzorzec pojawia się w niemal każdym zaawansowanym skrypcie RouterOS.

24Pętla foreach z poleceniem find

Najczęstsze zastosowanie foreach

Kluczowy wzorzec w RouterOS: użycie find do wyszukania elementów, a następnie foreach do przetworzenia każdego z nich.

Polecenie find zwraca listę wewnętrznych identyfikatorów (ID) elementów spełniających warunki.

# --- Przyklad: Wyswietl wszystkie aktywne interfejsy ---

:foreach iface in=[/interface find running] do={
    :local nazwa [/interface get $iface name]
    :local typ [/interface get $iface type]
    :put ("Interfejs: " . $nazwa . " (typ: " . $typ . ")")
}

# --- Przykład: Wyłącz wszystkie interfejsy nieaktywne ---

:foreach iface in=[/interface find running=no] do={
    :local nazwa [/interface get $iface name]
    :log warning ("Wyłączam nieaktywny interfejs: " . $nazwa)
    /interface disable $iface
}

Połączenie polecenia `find` z pętlą `:foreach` stanowi jeden z najważniejszych wzorców projektowych w skryptach RouterOS, umożliwiający przetwarzanie grup elementów konfiguracji według zadanych kryteriów. Polecenie `find` wyszukuje elementy spełniające warunek i zwraca ich identyfikatory, które następnie są przekazywane do pętli `:foreach`. Wewnątrz pętli dla każdego znalezionego identyfikatora można odczytać dowolne właściwości za pomocą `get` lub zmodyfikować je przez `set`.

Praktycznym przykładem jest skrypt wyświetlający wszystkie aktywne interfejsy wraz z ich nazwami i typami. Najpierw `find running` zwraca identyfikatory interfejsów o statusie aktywnym, następnie `:foreach` przechodzi przez każdy z nich, a wewnątrz pętli `get $iface name` i `get $iface type` pobierają szczegółowe dane. Możliwe jest także wykonywanie operacji modyfikujących, takich jak wyłączanie wszystkich nieaktywnych interfejsów. Ten wzorzec jest fundamentalny dla efektywnego zarządzania konfiguracją z poziomu skryptów.

25Pętla while i do-while

Pętla while - powtarzaj, dopóki warunek jest spełniony

while wykonuje blok kodu tak długo, jak warunek jest prawdziwy. Warunek jest sprawdzany przed każdym wykonaniem.

Składnia:

:while (warunek) do={
    # kod
}

UWAGA: Łatwo stworzyć nieskończącą się pętlę! Zawsze upewnij się, że warunek w końcu stanie się fałszywy.

# Przyklad: Licz od 5 do 1 (odliczanie)
:local licznik 5

:while ($licznik > 0) do={
    :put ("Zostało: " . $licznik)
    :set licznik ($licznik - 1)
}

# Przyklad: Znajdz pierwszy nieaktywny interfejs
:local znaleziono false
:local i 0

:while ($znaleziono = false) do={
    :if ($i > 10) do={
        :put "Nie znaleziono nieaktywnych interfejsów"
        :set znaleziono true
    }
    :set i ($i + 1)
}

# W RouterOS rzadko używamy while - foreach jest wygodniejszy

Pętla `:while` w RouterOS wykonuje blok kodu tak długo, jak podany warunek pozostaje prawdziwy, co czyni ją idealną do zadań, w których liczba iteracji nie jest znana z góry. Warunek jest sprawdzany przed każdym wykonaniem pętli, co oznacza, że jeśli od początku jest fałszywy, kod wewnątrz pętli nie wykona się ani razu. Należy zachować szczególną ostrożność przy używaniu `:while`, aby uniknąć stworzenia nieskończonej pętli, która może zablokować działanie routera lub doprowadzić do wyczerpania zasobów.

W RouterOS pętla `:while` jest używana rzadziej niż `:foreach`, ale znajduje zastosowanie w specyficznych scenariuszach, takich jak oczekiwanie na osiągnięcie określonego stanu systemu czy iteracja z warunkiem zakończenia zależnym od danych wejściowych. W większości typowych zadań administracyjnych, takich jak przetwarzanie list interfejsów czy reguł firewalla, pętla `:foreach` jest wygodniejsza i bezpieczniejsza. Pętla `:while` sprawdza się natomiast doskonale w sytuacjach, gdy warunek kontynuacji musi być dynamicznie oceniany w trakcie wykonywania pętli.

26Tablice (listy) - wprowadzenie

Co to jest tablica (lista)?

Tablica (lista, array) to zbiór wielu wartości przechowywanych pod jedną nazwą. Każdy element ma swój indeks (numer pozycji).

Wyobraź sobie szufladę z przegródkami ponumerowanymi od zera: w przegródce 0 jest pierwszy element, w przegródce 1 - drugi, itd.

Tworzenie tablicy:

:local mojaTablica {1, 2, 3, "tekst", 5.5}

Dostęp do elementów:

:pick $mojaTablica 0 - pobiera pierwszy element

[:len $mojaTablica] - zwraca liczbę elementów

# Tworzenie tablicy z różnymi typami danych
:local sieci {"192.168.1.0/24", "10.0.0.0/8", "172.16.0.0/12"}

# Sprawdzenie liczby elementów
:local ilosc [:len $sieci]
:put ("Liczba sieci: " . $ilosc)  # 3

# Dostęp do pierwszego elementu (indeks 0)
:local pierwszaSiec [:pick $sieci 0]
:put ("Pierwsza sieć: " . $pierwszaSiec)  # 192.168.1.0/24

# Dostęp do ostatniego elementu
:local ostatniaSiec [:pick $sieci ($ilosc - 1)]
:put ("Ostatnia sieć: " . $ostatniaSiec)  # 172.16.0.0/12

Tablice w RouterOS są strukturami danych umożliwiającymi przechowywanie wielu wartości pod jedną nazwą, co jest niezwykle przydatne przy grupowaniu powiązanych informacji. Każdy element tablicy ma swój indeks liczony od zera, a dostęp do niego odbywa się za pomocą funkcji `:pick $tablica indeks`. Tworzenie tablicy odbywa się przez umieszczenie elementów w nawiasach klamrowych oddzielonych przecinkami, na przykład `{1, 2, 3, "tekst", 5.5}`. Tablice w RouterOS mogą zawierać elementy różnych typów, co daje dużą elastyczność przy przechowywaniu różnorodnych danych.

Długość tablicy można sprawdzić za pomocą funkcji `[:len $tablica]`, która zwraca liczbę elementów jako wartość liczbową. W połączeniu z pętlą `:foreach` tablice pozwalają na efektywne przetwarzanie kolekcji danych bez konieczności ręcznego zarządzania indeksami. W praktyce tablice są używane do przechowywania list adresów IP, konfiguracji interfejsów, zestawów reguł czy tymczasowych wyników obliczeń. Zrozumienie mechanizmu indeksowania jest kluczowe, ponieważ dostęp do nieistniejącego indeksu może spowodować błąd wykonania skryptu.

27Tablice - operacje na elementach

Dodawanie i modyfikowanie elementów

RouterOS pozwala na dynamiczne modyfikowanie tablic:

  • Dodawanie elementu: :set (tablica->indeks) wartość
  • Pobieranie elementu: :pick $tablica indeks
  • Sprawdzenie długości: [:len $tablica]
# Tworzenie pustej tablicy
:global mojaTablica [:toarray ""]

# Dodawanie elementów
:set ($mojaTablica->0) "pierwszy"
:set ($mojaTablica->1) "drugi"
:set ($mojaTablica->2) "trzeci"

:put ("Liczba elementów: " . [:len $mojaTablica])

# Modyfikacja elementu
:set ($mojaTablica->1) "nowy drugi"

# Iteracja przez wszystkie elementy
:foreach element in=$mojaTablica do={
    :put ("Element: " . $element)
}

Operacje na tablicach w RouterOS obejmują dodawanie, modyfikowanie i usuwanie elementów, co pozwala na dynamiczne zarządzanie kolekcjami danych w trakcie wykonywania skryptu. Dodanie nowego elementu odbywa się przez przypisanie wartości do nieistniejącego wcześniej indeksu za pomocą składni `:set ($tablica->indeks) wartosc`. Modyfikacja istniejącego elementu wygląda identycznie, ale dotyczy już istniejącego indeksu, co powoduje nadpisanie poprzedniej wartości. Pobranie elementu realizuje funkcja `:pick $tablica indeks`.

Iteracja po wszystkich elementach tablicy za pomocą `:foreach` pozwala na wykonywanie operacji na każdym elemencie kolekcji bez konieczności znajomości jej rozmiaru. W praktyce tablice są często używane do akumulowania wyników, na przykład zbierania identyfikatorów interfejsów spełniających określone kryteria podczas iteracji. Mimo że RouterOS nie oferuje wbudowanych funkcji sortowania czy filtrowania tablic, te operacje można zaimplementować ręcznie za pomocą pętli `:foreach` i instrukcji warunkowych, co daje pełną kontrolę nad procesem przetwarzania danych.

28Tworzenie "funkcji" - :parse

Czy RouterOS ma funkcje?

RouterOS nie ma tradycyjnych funkcji jak języki programowania, ale możesz użyć polecenia :parse, aby stworzyć coś podobnego do funkcji - blok kodu, który można wywołać wielokrotnie.

Składnia:

:global nazwaFunkcji [:parse ":local a 1; :put \$a"]

Następnie wywołujesz: $nazwaFunkcji

Uwaga: Wewnątrz :parse używaj \$ zamiast $ dla zmiennych!

# Definicja funkcji "powitania"
:global powitaj [:parse ":put \"Witaj w RouterOS!\""]

# Wywołanie funkcji
$powitaj
$powitaj

# Funkcja z parametrem
:global powitajImieniem [:parse ":put (\"Witaj, \" . \$imie . \"!\")"]

# Wywołanie z parametrem
$powitajImieniem imie="Anna"
$powitajImieniem imie="Jan"

# Funkcja zwracająca wartość
:global obliczSume [:parse ":return ((\$a) + (\$b))"]
:local wynik [$obliczSume a=5 b=3]
:put ("Suma: " . $wynik)

Polecenie `:parse` w RouterOS umożliwia tworzenie konstrukcji przypominających funkcje z innych języków programowania poprzez dynamiczną kompilację kodu zapisanego w zmiennej. Składnia `:global mojaFunkcja [:parse ":put \"Witaj\""]` tworzy zmienną globalną przechowującą skompilowany kod, który można następnie wywołać przez `$mojaFunkcja`. Jest to szczególnie przydatne, gdy ten sam fragment kodu musi być wykonany wielokrotnie w różnych miejscach skryptu, ponieważ eliminuje konieczność powielania tych samych instrukcji.

Funkcje zdefiniowane za pomocą `:parse` mogą przyjmować parametry, które są przekazywane jako nazwane argumenty i dostępne wewnątrz kodu jako zmienne. Wewnątrz definicji funkcji należy używać `\$` zamiast `$` dla zmiennych, aby uniknąć przedwczesnej interpretacji. Funkcje mogą również zwracać wartości za pomocą polecenia `:return`, co pozwala na używanie ich w wyrażeniach przypisania. Mimo że `:parse` nie oferuje pełnej funkcjonalności funkcji znanej z zaawansowanych języków programowania, stanowi wystarczające narzędzie do organizacji kodu w większych projektach skryptowych.

29Praca z konfiguracją - find, get, set

Trzy filary zarządzania konfiguracją

Prawie każda operacja w skryptach RouterOS sprowadza się do trzech poleceń:

  • find - znajduje elementy spełniające warunki (zwraca ID)
  • get - pobiera wartość właściwości elementu
  • set - zmienia właściwości elementu

Schemat postępowania:

  1. Użyj find, aby znaleźć ID elementu
  2. Użyj get, aby odczytać właściwości
  3. Użyj set, aby zmienić właściwości
# Znajdz ID interfejsu o nazwie ether1
:local id [/interface find name="ether1"]

# Pobierz właściwość tego interfejsu (np. status running)
:local status [/interface get $id running]

# Zmień właściwość - wyłącz interfejs
/interface set $id disabled=yes

# Wszystko w jednym linii (bez zmiennych)
:if ([/interface get [find name="ether1"] running] = true) do={
    :put "Interfejs ether1 jest aktywny"
}

Praca z konfiguracją RouterOS opiera się na trzech fundamentalnych poleceniach: `find`, `get` i `set`, które razem tworzą spójny interfejs programistyczny do zarządzania każdym elementem systemu. Polecenie `find` wyszukuje elementy spełniające zadane kryteria i zwraca ich wewnętrzne identyfikatory, które są następnie używane przez `get` do odczytu właściwości lub przez `set` do ich modyfikacji. Ten trójstopniowy schemat postępowania pojawia się w niemal każdym skrypcie administracyjnym i stanowi podstawę interakcji z konfiguracją routera.

W praktyce administrator rzadko używa tych poleceń osobno, częściej łącząc je w jednej linii dla zwięzłości kodu. Na przykład wyrażenie `[/interface get [find name="ether1"] running]` w jednym kroku znajduje interfejs o nazwie ether1 i odczytuje jego właściwość running, zwracając true lub false. Takie zagnieżdżone wywołania są typowe dla zaawansowanych skryptów i pozwalają na pisanie kompaktowego, a jednocześnie czytelnego kodu. W przypadku bardziej złożonych operacji warto jednak rozbić proces na osobne kroki z użyciem zmiennych pośrednich.

30Dodawanie i usuwanie elementów - add, remove

Tworzenie nowych elementów

Polecenie add tworzy nowy wpis w konfiguracji:

/sciezka/add parametr1=wartosc1 parametr2=wartosc2

Usuwanie elementów

Polecenie remove usuwa element o danym ID:

/sciezka/remove [find warunek]

UWAGA: Usuniętego elementu nie można odzyskać!

# Dodaj nowy adres IP
/ip address add address=192.168.99.1/24 interface=ether2 comment="Nowy LAN"

# Dodaj regułę firewalla blokującą adres IP
/ip firewall address-list add list=blokowani address=1.2.3.4 comment="Atakujący"

# Znajdz i usun regulę
:local idReguly [/ip firewall address-list find address="1.2.3.4"]
:if ([:len $idReguly] > 0) do={
    /ip firewall address-list remove $idReguly
    :log info "Usunieto zablokowany adres IP"
}

# Usuń wszystkie wyłączone interfejsy
:foreach iface in=[/interface find disabled=yes] do={
    /interface remove $iface
}

Polecenia `add` i `remove` w RouterOS umożliwiają odpowiednio dodawanie nowych elementów do konfiguracji oraz usuwanie istniejących, co jest niezbędne przy dynamicznym zarządzaniu regułami firewalla, adresami IP, interfejsami i innymi zasobami. Dodanie nowego elementu wymaga podania ścieżki, na przykład `/ip address add address=192.168.99.1/24 interface=ether2`, oraz wszystkich wymaganych parametrów. Usunięcie elementu odbywa się przez podanie jego identyfikatora uzyskanego z polecenia `find`, na przykład `/ip firewall address-list remove [find address="1.2.3.4"]`.

Przed usunięciem elementu zawsze warto sprawdzić, czy `find` rzeczywiście znalazł jakiekolwiek identyfikatory, ponieważ próba usunięcia pustej listy zakończy się błędem. Warunek `:if ([:len $id] > 0)` przed wykonaniem `remove` stanowi standardowe zabezpieczenie w profesjonalnych skryptach. W przypadku operacji masowych, takich jak usunięcie wszystkich wyłączonych interfejsów, pętla `:foreach` w połączeniu z `find` i `remove` pozwala na przeprowadzenie operacji w jednym, czytelnym bloku kodu bez ryzyka pominięcia któregoś z elementów.

31Dostęp do elementów systemu

Pobieranie informacji o systemie

RouterOS oferuje wiele poleceń do odczytu informacji o urządzeniu:

  • /system identity get name - nazwa routera
  • /system resource get version - wersja RouterOS
  • /system clock get date - aktualna data
  • /system clock get time - aktualny czas
  • /interface print - lista interfejsów
  • /ip address print - lista adresów IP
# Pobierz podstawowe informacje o systemie
:local nazwaRoutera [/system identity get name]
:local wersja [/system resource get version]
:local data [/system clock get date]
:local czas [/system clock get time]
:local uptime [/system resource get uptime]

:put ("========================================")
:put ("Router: " . $nazwaRoutera)
:put ("Wersja RouterOS: " . $wersja)
:put ("Data: " . $data . " " . $czas)
:put ("Czas pracy: " . $uptime)
:put ("========================================")

# Sprawdz ilosc pamieci RAM
:local ram [/system resource get total-memory]
:local freeRam [/system resource get free-memory]
:put ("RAM calkowita: " . ($ram / 1024 / 1024) . " MB")
:put ("RAM wolna: " . ($freeRam / 1024 / 1024) . " MB")

Dostęp do informacji systemowych w RouterOS z poziomu skryptu pozwala na tworzenie narzędzi diagnostycznych i monitorujących, które mogą automatycznie raportować stan urządzenia. Polecenia takie jak `/system identity get name` zwracają nazwę routera, `/system resource get version` podaje wersję systemu operacyjnego, a `/system clock get date` i `/system clock get time` dostarczają bieżącą datę i czas. Te podstawowe informacje są często używane jako część nagłówka w generowanych raportach lub logach.

Bardziej zaawansowane dane systemowe, takie jak ilość pamięci RAM, czas pracy urządzenia czy obciążenie procesora, można uzyskać za pomocą poleceń w ścieżce `/system resource`. Na przykład pomiar całkowitej i wolnej pamięci RAM pozwala na obliczenie procentowego wykorzystania i wygenerowanie ostrzeżenia w przypadku przekroczenia krytycznego progu. Skrypty monitorujące mogą cyklicznie sprawdzać te wartości i w razie potrzeby wysyłać powiadomienia lub podejmować akcje naprawcze, co znacząco podnosi niezawodność infrastruktury sieciowej.

32Zapisywanie do logów systemowych

Po co nam logi?

Logi to zapis zdarzeń i działań systemu. Skrypty powinny zapisywać informacje o swoim działaniu do logów - dzięki temu możesz śledzić, co się dzieje i diagnozować problemy.

Polecenie :log

:log info "tekst" - zapisz informację

:log warning "tekst" - zapisz ostrzezenie

:log error "tekst" - zapisz blad

Dostęp do logów: /log print

# Podstawowe logowanie
:log info "Skrypt uruchomiony pomyslnie"
:log warning "Cos wymaga uwagi"
:log error "Wystapil blad!"

# Przykład: skrypt z logowaniem
:local interfejs "ether1"

:log info ("Rozpoczynam sprawdzanie interfejsu " . $interfejs)

:local status [/interface get [find name=$interfejs] running]

:if ($status = true) do={
    :log info ("Interfejs " . $interfejs . " jest aktywny - wszystko OK")
} else={
    :log error ("Interfejs " . $interfejs . " jest wylaczony! - wymaga interwencji!")
}

:log info "Skrypt zakonczony"

Logowanie zdarzeń w RouterOS za pomocą polecenia `:log` jest podstawowym mechanizmem rejestrowania informacji o działaniu skryptów i stanie urządzenia. Polecenie `:log info "tekst"` zapisuje komunikat informacyjny, `:log warning "tekst"` ostrzeżenie, a `:log error "tekst"` błąd, co pozwala na kategoryzowanie zdarzeń według ich ważności. Logi można następnie przeglądać za pomocą polecenia `/log print`, a odpowiednie filtry umożliwiają szybkie znajdowanie interesujących wpisów.

W profesjonalnych skryptach logowanie powinno być stosowane systematycznie, aby umożliwić śledzenie przebiegu wykonywania kodu i szybkie diagnozowanie problemów. Przed wykonaniem ważnej operacji warto zalogować jej rozpoczęcie, a po zakończeniu potwierdzenie sukcesu lub szczegóły błędu. Dobrze napisany skrypt loguje na poziomie info: normalne zdarzenia, na poziomie warning: sytuacje wymagające uwagi, a na poziomie error krytyczne awarie. Systematyczne logowanie jest szczególnie ważne w przypadku skryptów uruchamianych przez scheduler, gdzie administrator nie ma bieżącego wglądu w ich działanie.

33Argumenty skryptu

Czy skrypt może przyjmować argumenty?

Tak! Możesz przekazać do skryptu dodatkowe informacje (argumenty) podczas jego uruchamiania.

Jak uruchomić skrypt z argumentami:

/system script run nazwa_skryptu param1=wartosc1 param2=wartosc2

Jak odczytać argumenty w skrypcie:

Argumenty są dostępne jako zmienne globalne o nazwach zgodnych z nazwami parametrów.

# --- Skrypt: sprawdz-interfejs.rsc ---
# Oczekuje argumentow: interfejs, akcja

# Odczytaj argumenty (jeśli nie podane, użyj wartości domyślnych)
:global interfejs
:global akcja

:if ([:typeof $interfejs] = "nil") do={
    :set interfejs "ether1"
}
:if ([:typeof $akcja] = "nil") do={
    :set akcja "status"
}

:put ("Sprawdzam interfejs: " . $interfejs)
:put ("Akcja: " . $akcja)

# Uruchomienie:
# /system script run sprawdz-interfejs interfejs=ether2 akcja=info

Przekazywanie argumentów do skryptów RouterOS umożliwia tworzenie uniwersalnych narzędzi, które mogą być uruchamiane z różnymi parametrami bez konieczności modyfikacji kodu źródłowego. Argumenty są przekazywane podczas wywołania skryptu za pomocą składni `/system script run nazwa_skryptu parametr1=wartosc1 parametr2=wartosc2` i stają się dostępne wewnątrz skryptu jako zmienne globalne o nazwach zgodnych z nazwami parametrów. Dzięki temu ten sam skrypt może być używany w różnych kontekstach, na przykład do sprawdzania różnych interfejsów w zależności od podanego argumentu.

Ponieważ argumenty są zmiennymi globalnymi, przed ich użyciem należy sprawdzić, czy zostały przekazane podczas wywołania. Standardową praktyką jest sprawdzenie typu zmiennej za pomocą `:typeof` i w przypadku wartości `nil` ustawienie domyślnej wartości, co czyni argument opcjonalnym. Na przykład `:if ([:typeof $interfejs] = "nil") do={ :set interfejs "ether1" }` zapewnia, że skrypt będzie działał nawet bez podania argumentu. Ta technika pozwala na tworzenie elastycznych skryptów, które są jednocześnie łatwe w użyciu i odporne na błędy.

34Odczyt z plików

Czytanie zawartości plików

RouterOS pozwala na odczyt zawartości plików tekstowych zapisanych na routerze.

Jak odczytać plik:

/file get nazwa_pliku contents

Przydatne funkcje do pracy z tekstem:

  • [:len tekst] - zwraca długość tekstu
  • [:pick tekst od do] - pobiera fragment tekstu
  • [:find tekst szukany] - znajduje pozycję fragmentu
  • [:toarray tekst] - konwertuje tekst na tablicę (dzieli po przecinkach)
# Najpierw stworz plik testowy (np. przez export)
# /file print file=mojplik.txt

# Odczytaj zawartość pliku
:local zawartosc [/file get mojplik.txt contents]

:put ("Zawartosc pliku:")
:put $zawartosc

# Sprawdź długość tekstu
:local dlugosc [:len $zawartosc]
:put ("Dlugosc: " . $dlugosc . " znakow")

# Podziel tekst na elementy (zakładając format CSV - wartości po przecinkach)
:local elementy [:toarray $zawartosc]
:foreach elem in=$elementy do={
    :put ("Element: " . $elem)
}

Odczyt plików z systemu plików RouterOS z poziomu skryptu umożliwia przetwarzanie danych przechowywanych na routerze, takich jak pliki konfiguracyjne, logi czy raporty. Podstawowym poleceniem jest `/file get nazwa_pliku contents`, które zwraca zawartość pliku jako tekst, co pozwala na dalszą analizę za pomocą funkcji tekstowych. Przed odczytem warto sprawdzić, czy plik istnieje, aby uniknąć błędów wykonania skryptu w przypadku braku oczekiwanego pliku.

Funkcje tekstowe takie jak `:len` do sprawdzania długości, `:pick` do wycinania fragmentów, `:find` do wyszukiwania wzorców i `:toarray` do konwersji tekstu na tablicę umożliwiają zaawansowane przetwarzanie odczytanych danych. Na przykład po odczytaniu pliku z konfiguracją można podzielić go na linie za pomocą `:toarray` i przetworzyć każdą linię osobno w pętli `:foreach`. Ta technika jest szczególnie przydatna przy analizie wyeksportowanych konfiguracji lub przetwarzaniu danych z zewnętrznych systemów.

35Zapis do plików

Zapisywanie danych do plików

RouterOS ma specyficzny sposób tworzenia plików - nie można utworzyć pliku bezpośrednio, ale można użyć obejścia.

Metoda 1: Za pomocą /file print

/file print file=nowyplik.txt

Następnie ustaw zawartość: /file set nowyplik.txt contents="tekst"

Metoda 2: Eksport konfiguracji

/ip address export file=konfiguracja-ip.rsc

Tworzy plik z poleceniami potrzebnymi do odtworzenia konfiguracji.

# --- Tworzenie i zapisywanie do pliku ---

# Krok 1: Stwórz pusty plik
/file print file=raport.txt

# Krok 2: Zapisz do niego tekst
:local raport "To jest tresc raportu.\nData: "
:local data [/system clock get date]
:set raport ($raport . $data)

/file set raport.txt contents=$raport

# Krok 3: Sprawdź, czy plik został utworzony
:local pliki [/file print where name~"raport"]
:log info ("Utworzono plik, rozmiar listy: " . [:len $pliki])

# --- Praktyczny przykład: Eksport adresów IP ---
/ip address export file=adresy-ip
:log info "Wyeksportowano adresy IP do pliku adresy-ip.rsc"

Zapis danych do plików w RouterOS jest możliwy za pomocą specyficznego mechanizmu, który wymaga najpierw utworzenia pliku za pomocą polecenia `/file print file=nazwa.txt`, a następnie ustawienia jego zawartości przez `/file set nazwa.txt contents="tekst"`. Ta dwuetapowa procedura wynika z architektury systemu plików RouterOS, która nie pozwala na bezpośrednie tworzenie plików z zawartością. Alternatywną metodą jest eksport konfiguracji do pliku .rsc za pomocą polecenia `/export file=nazwa`, które tworzy plik z poleceniami przywracającymi bieżącą konfigurację.

W praktyce zapis do plików jest używany przede wszystkim do generowania raportów, tworzenia kopii zapasowych konfiguracji oraz logowania zdarzeń do plików zewnętrznych. Warto pamiętać, że pamięć flash routera ma ograniczoną pojemność, dlatego należy kontrolować rozmiar i liczbę przechowywanych plików. Automatyczne usuwanie starych plików lub nadpisywanie ich nowszymi wersjami to dobra praktyka, która zapobiega zapełnieniu pamięci urządzenia i związanym z tym problemom z wydajnością.

36Przydatne funkcje tekstowe

Operacje na tekstach (stringach)

RouterOS oferuje wiele funkcji do manipulacji tekstami:

  • [:len tekst] - zwraca długość tekstu
  • [:pick tekst od do] - pobiera fragment (od, do to indeksy)
  • [:find tekst szukany] - znajduje pozycję
  • [:replace tekst co czym] - zamienia fragment
  • [:tostr wartość] - konwertuje na tekst
  • [:tonum tekst] - konwertuje na liczbę
:local tekst "Hello World"

# Dlugosc tekstu
:put ("Dlugosc: " . [:len $tekst])  # 11

# Pobierz fragment (od znaku 0 do 5)
:put ([:pick $tekst 0 5])           # Hello

# Znajdz pozycję słowa
:put ([:find $tekst "World"])       # 6

# Zamień tekst
:local nowy [:replace $tekst "World" "RouterOS"]
:put $nowy                           # Hello RouterOS

# Konwersja typów
:local liczba 42
:local tekstZLiczby [:tostr $liczba]
:put ([:typeof $tekstZLiczby])       # str

:local tekstLiczbowy "123"
:local liczbaZTekstu [:tonum $tekstLiczbowy]
:put ([:typeof $liczbaZTekstu])      # num

Funkcje tekstowe w RouterOS stanowią bogaty zestaw narzędzi do manipulacji ciągami znaków, które są niezbędne przy przetwarzaniu danych wejściowych, formatowaniu komunikatów i analizie logów. Funkcja `:len` zwraca długość tekstu w znakach, `:pick` pozwala na wycięcie fragmentu tekstu od wskazanego indeksu początkowego do końcowego, a `:find` lokalizuje pozycję szukanego podtekstu w tekście. Funkcja `:replace` umożliwia zamianę fragmentu tekstu na inny, co jest przydatne przy maskowaniu danych lub normalizacji formatów.

Konwersje między typami realizują funkcje `:tostr` zamieniająca wartość dowolnego typu na tekst oraz `:tonum` konwertująca tekst na liczbę. Te funkcje są szczególnie przydatne przy przetwarzaniu danych pochodzących z różnych źródeł, takich jak pliki czy odpowiedzi z zapytań HTTP. W praktyce połączenie funkcji tekstowych z pętlami `:foreach` i instrukcjami warunkowymi pozwala na realizację zaawansowanego przetwarzania danych bez potrzeby używania zewnętrznych narzędzi. Opisane funkcje pokrywają większość typowych potrzeb związanych z manipulacją tekstem.

37Obsługa błędów - :do i :on-error

Co zrobić, gdy coś pójdzie nie tak?

Skrypt może napotkać błędy - np. próbować wyłączyć nieistniejący interfejs. Domyślnie skrypt wtedy się zatrzymuje. Możesz jednak obsłużyć błędy elegancko.

Składnia :do...on-error:

:do {
    # kod, który może się nie udać
} on-error={
    # kod wykonany, gdy wystąpi błąd
}
# Próba wyłączenia interfejsu (jeśli nie istnieje, skrypt nie zawiesi się)
/interface set ether1 disabled=yes

# Lepsza wersja z obsługą błędów
:do {
    :log info "Próba wyłączenia ether1..."
    /interface set ether1 disabled=yes
    :log info "Interfejs wyłączony"
} on-error={
    :log error "Nie udało się wyłączyć ether1 (może nie istnieje?)"
}

# Sprawdzenie, czy zmienna ma prawidłową wartość
:global mojaLista

:do {
    :local pierwszy [:pick $mojaLista 0]
    :put ("Pierwszy element: " . $pierwszy)
} on-error={
    :put "Lista jest pusta lub nie istnieje"
}

Obsługa błędów w RouterOS za pomocą konstrukcji `:do { kod } on-error={ kod }` pozwala na eleganckie radzenie sobie z sytuacjami wyjątkowymi bez przerywania działania skryptu. Blok `:do` zawiera kod, który potencjalnie może zakończyć się błędem, natomiast blok `on-error` jest wykonywany tylko w przypadku wystąpienia błędu, co pozwala na zareagowanie w kontrolowany sposób. Dzięki tej konstrukcji skrypt może kontynuować działanie nawet po napotkaniu problemu, na przykład próby wyłączenia nieistniejącego interfejsu czy odczytu pustej zmiennej.

W profesjonalnych skryptach `:do...on-error` powinno być używane zawsze, gdy istnieje ryzyko wystąpienia błędu, który nie powinien przerwać całego skryptu. Na przykład przy próbie wyłączenia interfejsu o nieznanej nazwie warto owinąć tę operację w blok `:do`, aby w razie błędu zalogować ostrzeżenie i kontynuować działanie. Należy jednak pamiętać, że `on-error` przechwytuje wszystkie błędy, dlatego warto logować informacje o błędzie, aby umożliwić późniejszą diagnozę. Bez tej konstrukcji każdy nieobsłużony błąd powoduje natychmiastowe zatrzymanie skryptu.

38Wybór wielowariantowy - switch-case

Czy RouterOS ma switch-case?

RouterOS nie ma bezpośredniej instrukcji switch-case jak w innych językach. Możesz jednak symulować jej działanie za pomocą serii instrukcji if-else lub :do-while z :break.

Alternatywny wzorzec - elseif:

Używaj :if z :else if (wielokrotne else):

:local status "aktywny"

# Symulacja switch-case za pomocą elseif
:if ($status = "aktywny") do={
    :put "Status: System działa poprawnie"
} else if ($status = "ostrzeżenie") do={
    :put "Status: Uwaga - możliwe problemy"
} else if ($status = "błąd") do={
    :put "Status: Krytyczny blad systemu"
} else={
    :put "Status: Nieznany"
}

# Przykład z akcjami
:local akcja "restart"

:if ($akcja = "start") do={
    :log info "Uruchamiam usluge"
} else if ($akcja = "stop") do={
    :log info "Zatrzymuje usluge"
} else if ($akcja = "restart") do={
    :log info "Restartuje usluge"
} else={
    :log warning ("Nieznana akcja: " . $akcja)
}

RouterOS nie oferuje bezpośredniej instrukcji switch-case znanej z innych języków programowania, ale jej funkcjonalność można z powodzeniem zastąpić serią instrukcji `:if` z `else if`. Konstrukcja `else if` pozwala na sprawdzenie wielu warunków w jednej strukturze decyzyjnej, gdzie każdy kolejny warunek jest sprawdzany tylko wtedy, gdy poprzednie nie zostały spełnione. Dzięki temu kod zachowuje się podobnie do switch-case, ale z większą elastycznością, ponieważ warunki mogą być dowolnie skomplikowane.

Alternatywnym wzorcem jest użycie pętli `:while` z instrukcją `:break`, ale w praktyce seria `else if` jest najczytelniejsza i najczęściej stosowana. Przykładowo obsługa różnych akcji administracyjnych, takich jak start, stop czy restart usługi, może być zaimplementowana przez sprawdzenie wartości zmiennej `$akcja` w serii warunków. Dla bardzo dużej liczby przypadków warto rozważyć użycie tablicy lub zmiennych globalnych jako mapy przechowującej skojarzenia między wartościami a akcjami, co dodatkowo upraszcza kod i ułatwia jego rozszerzanie.

39Praktyczny skrypt: Automatyczny backup

Automatyczne tworzenie kopii zapasowej

Backup to jeden z najważniejszych skryptów na każdym routerze. Powinien regularnie tworzyć kopie konfiguracji.

RouterOS oferuje dwa typy backupu:

  • .backup - binarny plik kopii zapasowej (szybko się przywraca)
  • .rsc - tekstowy plik z poleceniami (czytelny dla człowieka)

Dobry skrypt tworzy oba typy i nazywa pliki z datą.

# ==============================================
# Skrypt: backup-konfiguracji
# Automatyczny backup konfiguracji routera
# Uruchamiaj codziennie przez scheduler
# ==============================================

# --- Konfiguracja ---
:local przechowujOstatnie 7    # ile ostatnich backupów trzymać
# --------------------

:local routerName [/system identity get name]
:local dateStr [/system clock get date]

# Formatuj datę do postaci RRRR-MM-DD
:local formattedDate ([:pick $dateStr 7 11] . "-" . [:pick $dateStr 0 3] . "-" . [:pick $dateStr 4 6])

:local backupFileName ($routerName . "-" . $formattedDate)

:log info ("Rozpoczynam tworzenie backupu: " . $backupFileName)

# Twórz backup binarny
/system backup save name=$backupFileName
:log info "Backup binarny (.backup) utworzony"

# Twórz backup tekstowy
/export file=$backupFileName
:log info "Backup tekstowy (.rsc) utworzony"

# Opcjonalnie: wyślij e-mailem
# /tool e-mail send to="admin@firma.pl" subject=("Backup " . $routerName . " z " . $dateStr) file=($backupFileName . ".backup")

:log info "Tworzenie backupu zakonczone pomyslnie"

Praktyczny skrypt do automatycznego tworzenia kopii zapasowych konfiguracji routera jest jednym z najważniejszych narzędzi w arsenale każdego administratora MikroTik. Skrypt wykorzystuje polecenia `/system backup save` do utworzenia binarnego pliku .backup oraz `/export file` do eksportu konfiguracji w formacie tekstowym .rsc. Nazwa pliku generowana jest dynamicznie z użyciem nazwy routera i bieżącej daty, co zapewnia unikalność każdej kopii i umożliwia łatwe odtworzenie historii backupów.

Parametr konfiguracyjny określający liczbę przechowywanych ostatnich backupów pozwala na automatyczne zarządzanie miejscem na dysku bez ręcznej interwencji. Skrypt może być uruchamiany codziennie przez scheduler, co gwarantuje regularne tworzenie kopii zapasowych bez pamiętania o tym obowiązku. W bardziej zaawansowanej wersji można dodać wysyłanie plików backupu na zewnętrzny serwer FTP lub przez e-mail, co zabezpiecza konfigurację nawet w przypadku fizycznego uszkodzenia routera. Backup to podstawa bezpieczeństwa każdej infrastruktury sieciowej.

40Praktyczny skrypt: Aktualizacja DDNS

Dynamic DNS (DDNS)

Wiele łącz internetowych ma dynamicznie zmieniający się adres IP. DDNS pozwala na przypisanie stałej nazwy domenowej do zmiennego IP.

Ten skrypt sprawdza, czy adres IP uległ zmianie, i jeśli tak - aktualizuje wpis u dostawcy DDNS.

Uwaga: Składnia URL aktualizacji zależy od dostawcy DDNS.

# ==============================================
# Skrypt: aktualizacja-ddns
# Sprawdza i aktualizuje adres IP w usłudze DDNS
# ==============================================

# --- Konfiguracja (dostosuj do swojego dostawcy DDNS) ---
:local ddnsHost "twoja-domena.pl"
:local ddnsUser "twoj uzytkownik"
:local ddnsPass "twoje haslo"
:local ddnsInterface "pppoe-out1"
# UWAGA: Zmień URL aktualizacji zgodnie z dokumentacją dostawcy DDNS
:local updateUrl "https://twoj-ddns.pl/nic/update?hostname=HOST&myip=IP"
# -------------------------------------------------------------

:global lastKnownIp

# Pobierz aktualny adres IP z interfejsu WAN
:local currentIp [/ip address get [find interface=$ddnsInterface] address]

# Usuń maskę sieci (np. 192.168.1.100/24 -> 192.168.1.100)
:set currentIp [:pick $currentIp 0 [:find $currentIp "/"]]

# Sprawdź, czy adres się zmienił
:if ($currentIp != $lastKnownIp) do={
    :log info ("DDNS: Wykryto nowy adres IP: " . $currentIp)
    
    # Zbuduj URL aktualizacji
    :local url [:replace $updateUrl "HOST" $ddnsHost]
    :set url [:replace $url "IP" $currentIp]
    
    # Wyślij żądanie aktualizacji
    /tool fetch url=$url keep-result=no mode=https
    
    # Zapamiętaj nowy adres
    :set lastKnownIp $currentIp
    :log info "DDNS: Adres IP zaktualizowany"
} else={
    :log info ("DDNS: Adres IP bez zmian (" . $currentIp . ")")
}

Dynamiczny DNS (DDNS) to usługa, która mapuje zmienny adres IP na stałą nazwę domenową, co jest niezbędne w przypadku łączy internetowych z dynamicznie przydzielanym adresem. Skrypt aktualizujący DDNS w RouterOS sprawdza bieżący adres IP interfejsu WAN i porównuje go z zapamiętaną poprzednią wartością przechowywaną w zmiennej globalnej. Jeśli adres uległ zmianie, skrypt wysyła żądanie HTTP do API dostawcy DDNS z nowym adresem, a następnie zapamiętuje go jako bieżący.

Zmienna globalna `lastKnownIp` przechowuje ostatni znany adres IP, co pozwala na wykrycie zmiany i aktualizację tylko wtedy, gdy jest to konieczne. Dzięki temu skrypt nie wysyła niepotrzebnych żądań do API dostawcy przy każdym uruchomieniu, co oszczędza zasoby sieciowe i obliczeniowe. W konfiguracji skryptu należy podać dane dostępowe do usługi DDNS, adres URL aktualizacji oraz nazwę interfejsu WAN. Skrypt powinien być uruchamiany przez scheduler co 5-30 minut w zależności od wymaganej szybkości reakcji na zmianę adresu IP.

41Praktyczny skrypt: Ochrona przed atakami SSH

Automatyczne blokowanie ataków brute-force

Publicznie dostępne usługi SSH są nieustannie atakowane. Ten skrypt analizuje logi i automatycznie blokuje adresy IP, z których pochodzą nieudane próby logowania.

Wymagania wstępne:

  • Reguła firewalla blokująca ruch z listy "ssh-blacklist"
  • Uruchamianie skryptu co 1-5 minut przez scheduler
# ==============================================
# Skrypt: blokuj-atakujacych-ssh
# Automatycznie blokuje adresy IP atakujące SSH
# ==============================================

# Znajdz wpisy w logach dotyczacych nieudanych logowan SSH
:local failedLogins [/log find message~"login failure.*via ssh"]

:if ([:len $failedLogins] > 0) do={
    :foreach logEntry in=$failedLogins do={
        :local logLine [/log get $logEntry message]
        
        # Wyciągnij adres IP z logu (format: "login failure for user admin from 1.2.3.4 via ssh")
        :local ipStart ([:find $logLine "from "] + 5)
        :local viaPos [:find $logLine " via"]
        :local remoteIp [:pick $logLine $ipStart $viaPos]
        
        # Sprawdź, czy adres nie jest już na czarnej liście
        :local jestNaLiscie [/ip firewall address-list find list="ssh-blacklist" address=$remoteIp]
        
        :if ([:len $jestNaLiscie] = 0) do={
            :log warning ("Blokuje adres IP atakujacego SSH: " . $remoteIp)
            
            # Dodaj do czarnej listy na 1 dzień (timeout=1d)
            /ip firewall address-list add list="ssh-blacklist" address=$remoteIp \
                comment="Auto-block SSH brute-force" timeout=1d
        }
    }
}

:log info "Sprawdzanie atakow SSH zakonczone"

Automatyczna ochrona przed atakami brute-force na usługę SSH to jeden z najbardziej praktycznych skryptów zabezpieczających, które można wdrożyć na routerze MikroTik. Skrypt analizuje logi systemowe w poszukiwaniu wpisów dotyczących nieudanych prób logowania SSH, a następnie wyodrębnia adresy IP atakujących i dodaje je do czarnej listy firewalla. Dzięki temu po kilku nieudanych próbach logowania atakujący zostaje automatycznie zablokowany na określony czas, co skutecznie uniemożliwia dalsze próby włamania.

Wymaganiem wstępnym jest istnienie reguły firewalla blokującej ruch z listy adresowej `ssh-blacklist`, która jest dynamicznie uzupełniana przez skrypt. Parametr `timeout=1d` przy dodawaniu adresu do listy zapewnia automatyczne usunięcie blokady po 24 godzinach, co zapobiega trwałemu blokowaniu legalnych użytkowników, którzy mogli pomylić hasło. Skrypt powinien być uruchamiany przez scheduler co 1-5 minut dla szybkiej reakcji na atak. To rozwiązanie znacząco podnosi bezpieczeństwo zdalnego dostępu do routera bez konieczności ręcznego monitorowania logów.

42Automatyczne reagowanie z Netwatch

Netwatch - monitoring hostów

Netwatch to narzędzie, które cyklicznie pinguje określone hosty i może uruchamiać skrypty gdy host przestanie odpowiadać (down) lub zacznie odpowiadać ponownie (up).

Zmienne automatyczne w skrypcie Netwatch:

  • $host - adres IP monitorowanego hosta
  • $status - aktualny stan ("up" lub "down")

Jak skonfigurować:

/tool netwatch add host=8.8.8.8 interval=10s on-down-script=skrypt-alarm on-up-script=skrypt-ok

# ==============================================
# Skrypt: netwatch-alerter
# Uruchamiany przez Netwatch przy zmianie stanu hosta
# ==============================================

:global host      # automatycznie ustawiane przez Netwatch
:global status    # automatycznie ustawiane przez Netwatch ("up" lub "down")

:local message

:if ($status = "down") do={
    :set message ("ALARM: Host " . $host . " nie odpowiada!")
    :log error $message
    
    # Możesz dodać dodatkowe akcje:
    # - Wysłanie e-maila
    # - Przełączenie na zapasowe łącze
    # - Odtworzenie alarmu
    
} else={
    :set message ("OK: Host " . $host . " jest ponownie dostępny")
    :log info $message
    
    # Akcja przy powrocie do normy
}

# --- Przykładowa konfiguracja Netwatch ---
# /tool netwatch add host=8.8.8.8 interval=10s on-down-script=netwatch-alerter on-up-script=netwatch-alerter
# Skrypt "netwatch-alerter" musi być najpierw zapisany w /system script

Netwatch to wbudowane narzędzie w RouterOS, które cyklicznie monitoruje dostępność wskazanych hostów za pomocą ping i może uruchamiać skonfigurowane skrypty w przypadku zmiany stanu hosta z dostępnego na niedostępny i odwrotnie. Konfiguracja Netwatch jest prosta i sprowadza się do dodania wpisu za pomocą polecenia `/tool netwatch add host=8.8.8.8 interval=10s`, gdzie `host` to adres IP monitorowanego urządzenia, a `interval` to odstęp między kolejnymi sprawdzeniami. Z Netwatch można skojarzyć dwa skrypty: jeden uruchamiany przy stwierdzeniu braku dostępności, drugi przy jej przywróceniu.

Wewnątrz skryptu uruchamianego przez Netwatch dostępne są dwie automatyczne zmienne: `$host` zawierająca adres monitorowanego hosta oraz `$status` z wartością `up` lub `down`. Dzięki tym zmiennym ten sam skrypt może być używany zarówno do obsługi zdarzenia awarii, jak i przywrócenia dostępności, poprzez sprawdzenie wartości `$status` w instrukcji warunkowej. Netwatch znajduje zastosowanie w monitorowaniu łączy internetowych, serwerów, routerów sąsiednich oraz wszędzie tam, gdzie potrzebna jest automatyczna reakcja na zmianę dostępności zasobu sieciowego.

43Dobre praktyki pisania skryptów

Zasady pisania czytelnych i bezpiecznych skryptów

  • Dodawaj komentarze - wyjaśniaj co robi dany fragment kodu
  • Używaj opisowych nazw zmiennych - zamiast "x" napisz "licznikProbow"
  • Grupuj kod - oddzielaj sekcje pustymi liniami
  • Sprawdzaj błędy - używaj :do...on-error
  • Nie powtarzaj kodu - jeśli coś robisz wielokrotnie, rozważ pętlę
  • Testuj na bezpiecznym środowisku - przed wdrożeniem przetestuj skrypt
  • Loguj ważne zdarzenia - :log info/warning/error
  • Uważaj na zmienne globalne - używaj ich tylko gdy konieczne

Przykład dobrego skryptu:

# ==============================================
# Skrypt: sprawdz-pamiec
# Sprawdza wykorzystanie pamieci RAM
# ==============================================

# --- Konfiguracja ---
:local progOstrzezenia 80    # % pamięci, gdy ostrzegamy
# --------------------

# Pobierz dane o pamięci
:local totalRam [/system resource get total-memory]
:local freeRam [/system resource get free-memory]

# Oblicz procent wykorzystania
:local usedRam ($totalRam - $freeRam)
:local percentUsed (($usedRam * 100) / $totalRam)

# Sprawdź i zaloguj
:if ($percentUsed > $progOstrzezenia) do={
    :log warning ("UWAGA: Pamiec RAM na " . $percentUsed . "%! Moze brakowac RAM.")
    :put ("Ostrzezenie: Pamiec na " . $percentUsed . "%")
} else={
    :log info ("Pamiec RAM na " . $percentUsed . "% - stan OK")
    :put ("RAM: " . $percentUsed . "%")
}

Przestrzeganie dobrych praktyk przy pisaniu skryptów RouterOS jest kluczowe dla utrzymania czytelności, niezawodności i bezpieczeństwa kodu w dłuższej perspektywie. Przede wszystkim każdy skrypt powinien zawierać komentarz nagłówkowy z nazwą, autorem, datą i opisem przeznaczenia, co ułatwia zarządzanie większą liczbą skryptów na jednym urządzeniu. Nazwy zmiennych powinny być opisowe i jednoznaczne, na przykład `licznikProbow` zamiast `x`, a kod powinien być grupowany w logiczne sekcje oddzielone pustymi liniami dla lepszej czytelności.

Obsługa błędów za pomocą `:do...on-error` powinna być stosowana we wszystkich miejscach, gdzie istnieje ryzyko wystąpienia wyjątku, aby zapobiec nieoczekiwanemu przerwaniu skryptu. Logowanie ważnych zdarzeń za pomocą `:log` z odpowiednim poziomem ważności pozwala na monitorowanie działania skryptów i szybkie diagnozowanie problemów. Zmienne globalne należy używać oszczędnie i tylko wtedy, gdy jest to naprawdę konieczne, preferując zmienne lokalne o ograniczonym zakresie widoczności. Przed wdrożeniem na produkcji każdy skrypt warto przetestować w bezpiecznym środowisku laboratoryjnym.

44Typowe błędy i jak ich unikać

Częste problemy początkujących

  • Zapomnienie $ przed nazwą zmiennej
    Prawidłowo: :put $mojaZmienna
    Błędnie: :put mojaZmienna (wyświetli słowo "mojaZmienna" zamiast wartości)
  • Nawiasy w konkatenacji
    Prawidłowo: "Wynik: " . $liczba
    Wewnątrz wyrażeń: ("Wynik: " . $liczba)
  • Nieskończone pętle
    Zawsze upewnij się, że warunek wyjścia będzie spełniony!
  • Mylenie = z ==
    W RouterOS porównanie to =, nie ==
  • Nieistniejące elementy
    Sprawdź czy find coś znalazł: :if ([:len $znalezione] > 0)
# --- Poprawne i bledne przyklady ---

# BŁĄD: Zapomniane $
:local x 10
:put "x"           # Wyswietli: x (tekst!)
:put $x            # Wyswietli: 10 (wartosc)

# POPRAWNIE: Nawiasy w wyrażeniach
:put "Wynik: " . $x           # Działa
:put ("Wynik: " . ($x + 5))   # Działa

# POPRAWNIE: Sprawdzenie czy coś znaleziono
:local id [/interface find name="nieistnieje"]
:if ([:len $id] > 0) do={
    # Coś znaleziono
} else={
    :log info "Nie znaleziono interfejsu"
}

# POPRAWNIE: Porównanie
:if ($x = 10) do={}   # POPRAWNE
:if ($x == 10) do={}  # BŁĄD - nie używaj ==

Znajomość typowych błędów popełnianych przez początkujących przy pisaniu skryptów RouterOS pozwala ich unikać i znacząco przyspiesza proces nauki. Najczęstszym problemem jest zapominanie znaku `$` przed nazwą zmiennej, co powoduje, że RouterOS traktuje nazwę jako zwykły tekst, a nie odwołanie do zmiennej. Kolejnym częstym błędem jest nieprawidłowe stosowanie nawiasów przy konkatenacji, gdzie brak nawiasów wokół wyrażenia prowadzi do nieoczekiwanych rezultatów lub błędów składniowych.

Nieskończone pętle powstają, gdy warunek zakończenia pętli `:while` nigdy nie staje się fałszywy, co może zablokować działanie routera i wymagać restartu. Mylenie operatora porównania `=` z podwójnym `==` znanym z innych języków również prowadzi do błędów, ponieważ w RouterOS `==` nie jest poprawnym operatorem. Próba użycia nieistniejącego elementu bez uprzedniego sprawdzenia go za pomocą `find` i weryfikacji długości wyniku to kolejna typowa pułapka. Zaleca się zawsze sprawdzać `:if ([:len $id] > 0)` przed wykonaniem operacji na znalezionych elementach.

45Debugowanie skryptów

Jak znaleźć błąd w skrypcie?

Debugowanie to proces szukania i naprawiania błędów w skrypcie. Oto najważniejsze techniki:

  • :put - wyświetla wartość w konsoli (tylko przy ręcznym uruchomieniu)
  • :log info/warning/error - zapisuje do logów (zawsze działa)
  • Komentowanie fragmentów - wyłączaj części kodu, aby znaleźć błąd
  • Testuj stopniowo - uruchamiaj małe fragmenty, nie cały skrypt
# ==============================================
# Techniki debugowania
# ==============================================

# 1. Wyswietl wartosc zmiennej
:local mojaWartosc 42
:put ("DEBUG: mojaWartosc = " . $mojaWartosc)

# 2. Zapisz informację w logu
:log info ("DEBUG: Dotarlem do tego miejsca, zmienna = " . $mojaWartosc)

# 3. Sprawdź typ zmiennej
:put ("DEBUG: Typ zmiennej = " . [:typeof $mojaWartosc])

# 4. Komentowanie fragmentów kodu
# Zakomentuj całą sekcję, dodając # przed każdą linię:
# :local staraWartosc 100
# :set mojaWartosc $staraWartosc
# :log info "To jest wyłączone"

# 5. Sprawdzenie warunku krok po kroku
:local x 5
:put ("x = " . $x)
:if ($x > 0) do={
    :put "x jest większe od 0"
    :if ($x > 3) do={
        :put "x jest większe od 3"
    }
}

Debugowanie skryptów RouterOS to umiejętność niezbędna przy tworzeniu i utrzymaniu kodu, która pozwala skutecznie lokalizować i naprawiać błędy. Najprostszą techniką debugowania jest używanie polecenia `:put` do wyświetlania wartości zmiennych w konsoli, co pozwala na bieżąco śledzić przepływ danych przez skrypt. Ponieważ `:put` działa tylko przy ręcznym uruchomieniu, dla skryptów wykonywanych przez scheduler lepszym wyborem jest `:log info`, które zapisuje komunikaty do logów systemowych dostępnych przez `/log print`.

Komentowanie fragmentów kodu poprzez dodanie `#` na początku linii pozwala tymczasowo wyłączać podejrzane sekcje i sprawdzać, czy błąd nadal występuje. Sprawdzanie typu zmiennej za pomocą `:typeof` pomaga zdiagnozować problemy związane z niezgodnością typów, na przykład gdy zmienna oczekiwana jako liczba w rzeczywistości zawiera tekst. W przypadku złożonych warunków warto rozbić je na kilka osobnych kroków, wyświetlając wartości pośrednie. Stopniowe testowanie małych fragmentów kodu zamiast uruchamiania całego skryptu naraz znacząco ułatwia identyfikację źródła problemu.

46Praktyczny skrypt: Czyszczenie starych logów

Automatyczne usuwanie starych logów

Logi zajmują miejsce w pamięci routera. Ten skrypt regularnie usuwa stare logi, aby zwolnić miejsce.

Ważne: starsze logi mogą być potrzebne do diagnozowania problemów, więc nie usuwaj ich zbyt agresywnie!

# ==============================================
# Skrypt: czysczenie-logow
# Usuwa stare logi systemowe
# ==============================================

# --- Konfiguracja ---
:local ileDniTrzymac 7    # ile dni logów zachować
# --------------------

:log info "Rozpoczynam czyszczenie starych logow"

# Policz logi przed
:local logiPrzed [/log print count-only]
:put ("Logów przed czyszczeniem: " . $logiPrzed)

# Znajdz stare logi (starsze niz X dni)
# RouterOS nie ma prostej funkcji "logi starsze niż", 
# ale możemy usunąć logi powyżej określonej liczby:
:local maxLogow 1000    # maksymalna liczba logów do zachowania

:local aktualnaLiczbaLogow [/log print count-only]

:if ($aktualnaLiczbaLogow > $maxLogow) do={
    :local doUsuniecia ($aktualnaLiczbaLogow - $maxLogow)
    :log info ("Usuwam " . $doUsuniecia . " najstarszych logow")
    
    # Pobierz najstarsze logi i usuń je
    :local stareLogi [:pick [/log print as-value] 0 $doUsuniecia]
    :foreach log in=$stareLogi do={
        /log remove [find .id=$log]
    }
} else={
    :log info "Nie ma logow do usuniecia"
}

# Policz logi po
:local logiPo [/log print count-only]
:put ("Logów po czyszczeniu: " . $logiPo)
:log info ("Czyszczenie logow zakonczone. Usunieto: " . ($logiPrzed - $logiPo))

Praktyczny skrypt do czyszczenia starych logów jest niezbędnym narzędziem na każdym routerze produkcyjnym, ponieważ logi systemowe mogą szybko wypełnić ograniczoną pamięć flash urządzenia. Skrypt porównuje bieżącą liczbę wpisów logów z maksymalną dopuszczalną wartością i w przypadku przekroczenia progu usuwa najstarsze wpisy. Parametr konfiguracyjny `maxLogow` określa, ile wpisów logów maksymalnie ma być przechowywanych, co pozwala dostosować działanie skryptu do indywidualnych potrzeb i dostępnej przestrzeni dyskowej.

Przed i po czyszczeniu skrypt zlicza logi oraz wyświetla i loguje liczbę usuniętych wpisów, co umożliwia monitorowanie skuteczności działania. Należy zachować umiar przy ustawianiu progu usuwania, ponieważ zbyt agresywne czyszczenie może usunąć logi potrzebne do diagnozowania problemów z siecią. Zaleca się przechowywanie co najmniej 1000 ostatnich wpisów i uruchamianie skryptu raz dziennie. W przypadku konieczności przechowywania logów przez dłuższy czas warto rozważyć konfigurację zewnętrznego serwera logów zamiast polegania na ograniczonej pamięci routera.

47Praktyczny skrypt: Failover (przełączenie awaryjne)

Automatyczne przełączenie na zapasowe łącze

Failover to mechanizm automatycznego przełączania na zapasowe łącze internetowe, gdy główne łącze przestanie działać.

Ten skrypt sprawdza dostępność głównego łącza i w razie problemów aktywuje zapasowe.

# ==============================================
# Skrypt: sprawdz-failover
# Sprawdza główne łącze i przełącza na zapasowe
# ==============================================

# --- Konfiguracja ---
:local glownyHost 8.8.8.8        # host do pingowania (np. DNS Google)
:local interfejsGlowny "pppoe-out1"
:local interfejsZapasowy "ether3"
# --------------------

:global czyZapasoweAktywne

# Sprawdź, czy główne łącze działa
:local pingWynik [/ping $glownyHost count=3 interface=$interfejsGlowny]

:if ($pingWynik > 0) do={
    # Główne łącze działa
    :if ($czyZapasoweAktywne = true) do={
        :log info "Główne łącze działa, powracam z zapasowego"
        # Wyłącz zapasowe łącze
        /interface disable $interfejsZapasowy
        :set czyZapasoweAktywne false
    }
} else={
    # Główne łącze nie działa
    :if ($czyZapasoweAktywne = false) do={
        :log warning ("Glowne lacze nie dziala! Przelaczam na zapasowe!")
        # Włącz zapasowe łącze
        /interface enable $interfejsZapasowy
        :set czyZapasoweAktywne true
    } else={
        :log warning "Glowne lacze nadal nie dziala, zapasowe juz aktywne"
    }
}

Skrypt failover do automatycznego przełączania między głównym a zapasowym łączem internetowym to zaawansowane narzędzie zapewniające ciągłość działania sieci nawet w przypadku awarii podstawowego dostawcy usług internetowych. Skrypt cyklicznie pinguje wskazany host przez interfejs głównego łącza, a w przypadku braku odpowiedzi przez zadany czas automatycznie aktywuje zapasowe łącze, zmieniając domyślną trasę i powiadamiając administratora o zdarzeniu. Zmienna globalna `czyZapasoweAktywne` przechowuje bieżący stan, aby uniknąć wielokrotnego przełączania przy kolejnych uruchomieniach.

Po przywróceniu działania głównego łącza skrypt automatycznie przełącza się z powrotem na nie i dezaktywuje łącze zapasowe, przywracając domyślną konfigurację routingu. Parametry konfiguracyjne, takie jak adres hosta testowego, nazwy interfejsów czy liczba pingów testowych, są zdefiniowane na początku skryptu, co ułatwia dostosowanie go do konkretnego środowiska sieciowego. Skrypt powinien być uruchamiany przez scheduler co 30-60 sekund, aby zapewnić szybką reakcję na awarię łącza bez zbędnego obciążania systemu zbyt częstymi sprawdzeniami.

48Środowisko skryptów i zmienne systemowe

Dostępne zmienne automatyczne

RouterOS udostępnia pewne zmienne automatycznie w środowisku skryptów:

  • $host - w Netwatch: adres monitorowanego hosta
  • $status - w Netwatch: "up" lub "down"
  • Obiekty konfiguracji - można je pobierać bezpośrednio

Środowisko skryptów:

/system script environment print - wyświetla wszystkie zmienne globalne

Możesz tam zobaczyć zmienne zdefiniowane przez :global.

# --- Przegladanie zmiennych srodowiska ---

# Wyswietl srodowisko skryptow
:put "Zmienne globalne w środowisku:"
/system script environment print

# --- Definiowanie zmiennych konfiguracyjnych ---
# Zamiast wpisywać wartości bezpośrednio w kodzie,
# możesz użyć zmiennych globalnych jako "konfiguracji"

:global cfgInterwal 5m
:global cfgEmailAdmin "admin@firma.pl"
:global cfgDebugMode true

# W kodzie używasz zmiennych:
:if ($cfgDebugMode = true) do={
    :put ("Debug: Interwal = " . $cfgInterwal)
}

# --- Aktualizacja konfiguracji bez edycji skryptu ---
# Możesz zmienić wartość zmiennej globalnej bez edycji skryptu:
# /system script environment set cfgDebugMode false

Środowisko skryptów i zmienne systemowe w RouterOS stanowią kontekst, w którym wykonywany jest każdy skrypt, wpływając na dostępne zasoby i możliwości. Zmienne globalne zdefiniowane przez `:global` są przechowywane w specjalnym obszarze pamięci zwanym środowiskiem skryptów, który można przeglądać za pomocą polecenia `/system script environment print`. To polecenie wyświetla wszystkie zdefiniowane zmienne globalne wraz z ich bieżącymi wartościami, co jest przydatne przy debugowaniu i audytowaniu konfiguracji.

Zmienne globalne doskonale nadają się do przechowywania wartości konfiguracyjnych, które są wspólne dla wielu skryptów, takich jak adresy serwerów, progi ostrzegawcze czy identyfikatory interfejsów. Dzięki temu zmiana konfiguracji w jednym miejscu automatycznie aktualizuje działanie wszystkich skryptów korzystających z danej zmiennej, bez konieczności edycji każdego z osobna. Zmienne środowiskowe można modyfikować zarówno z poziomu skryptu przez `:set`, jak i ręcznie przez polecenie `/system script environment set`. Systematyczne korzystanie z tego mechanizmu podnosi elastyczność i łatwość utrzymania skryptów.

49Podsumowanie wykładu

Czego się nauczyliśmy?

W tym wykładzie omówiliśmy podstawy skryptowania w MikroTik RouterOS:

  • Zmienne - lokalne (:local) i globalne (:global)
  • Typy danych - tekst, liczby, IP, logika, tablice
  • Operatory - arytmetyczne, porównania, logiczne
  • Instrukcje warunkowe - if, else, elseif
  • Pętle - for, foreach, while
  • Praca z konfiguracją - find, get, set, add, remove
  • Tablice i listy - przechowywanie wielu wartości
  • Funkcje - :parse do tworzenia wielokrotnego kodu
  • Obsługa błędów - :do...on-error
  • Logowanie i debugowanie

Co dalej?

Praktykuj! Zaczynaj od prostych skryptów i stopniowo zwiększaj ich złożoność. Czytaj dokumentację MikroTik i analizuj skrypty społeczności.

Podsumowanie wykładu zestawia wszystkie kluczowe zagadnienia związane ze skryptowaniem w RouterOS, które zostały omówione w trakcie kursu. Uczestnik poznał podstawy deklaracji zmiennych lokalnych i globalnych, typy danych dostępne w języku oraz operatory arytmetyczne, porównania i logiczne. Instrukcje warunkowe i pętle zostały zaprezentowane zarówno od strony teoretycznej, jak i praktycznej, z przykładami rzeczywistych zastosowań w administracji sieciowej. Praca z konfiguracją za pomocą `find`, `get`, `set`, `add` i `remove` stanowi fundament interakcji skryptów z systemem.

Zaawansowane tematy, takie jak obsługa błędów, tworzenie funkcji za pomocą `:parse` oraz techniki debugowania, przygotowują uczestnika do samodzielnego rozwiązywania problemów i tworzenia własnych narzędzi. Praktyczne skrypty do backupu, DDNS, ochrony SSH i failover pokazują, jak w kilkudziesięciu liniach kodu zrealizować wartościowe narzędzia administracyjne. Kluczem do dalszego rozwoju jest systematyczna praktyka, eksperymentowanie z własnymi pomysłami oraz korzystanie z bogatej dokumentacji i społeczności MikroTik dostępnej w internecie.

50Gdzie szukać pomocy i więcej informacji?

Oficjalna dokumentacja MikroTik

  • Dokumentacja RouterOS: help.mikrotik.com
  • Wiki MikroTik: wiki.mikrotik.com
  • Forum społeczności: forum.mikrotik.com

Inne przydatne źródła

  • Dokumentacja Scripting na stronie help.mikrotik.com/docs/display/ROS/Scripting
  • Przykłady skryptów w oficjalnej dokumentacji
  • Kanały YouTube poświęcone RouterOS

Dobre praktyki

  • Zawsze testuj skrypty na maszynie wirtualnej lub nieprodukcyjnym urządzeniu
  • Korzystaj z opcji eksportu konfiguracji przed wprowadzeniem zmian
  • Dokumentuj swoje skrypty komentarzami

Dziękuję za uwagę!

Masz pytania? Chętnie na nie odpowiem.

Źródła wiedzy i pomocy przy pracy z RouterOS są niezwykle bogate i dostępne zarówno w formie oficjalnej dokumentacji, jak i społecznościowych forów dyskusyjnych. Oficjalna dokumentacja dostępna na stronie help.mikrotik.com zawiera szczegółowe opisy wszystkich poleceń, przykładów konfiguracji i poradników krok po kroku. Wiki MikroTik na wiki.mikrotik.com to kolejne cenne źródło wiedzy tworzone przez społeczność, zawierające praktyczne porady i gotowe rozwiązania typowych problemów. Forum społeczności na forum.mikrotik.com umożliwia zadawanie pytań i dzielenie się doświadczeniami z innymi administratorami.

Dokumentacja dotycząca skryptowania dostępna jest w sekcji help.mikrotik.com/docs/display/ROS/Scripting i zawiera pełną specyfikację języka, opisy wszystkich funkcji i poleceń skryptowych oraz liczne przykłady. Kanały YouTube poświęcone MikroTik oferują wizualne tutoriale prezentujące praktyczne zastosowania skryptów w rzeczywistych scenariuszach sieciowych. Przed wdrożeniem jakiegokolwiek skryptu na produkcji zaleca się przetestowanie go w środowisku laboratoryjnym, na przykład z użyciem darmowego obrazu RouterOS dla platformy wirtualnej x86. Systematyczne korzystanie z wymienionych źródeł wiedzy znacząco przyspiesza rozwój umiejętności.

51Dodatek: Przydatne polecenia skryptowe

Krótka ściągawka z najważniejszych poleceń

Deklaracje:

  • :local nazwa wartość - zmienna lokalna
  • :global nazwa wartość - zmienna globalna
  • :set zmienna wartość - modyfikacja zmiennej

Sterowanie:

  • :if (warunek) do={} - warunek
  • :for i from=x to=y do={} - pętla liczbowa
  • :foreach zmienna in=kolekcja do={} - pętla po elementach
  • :while (warunek) do={} - pętla dopóki

Systemowe:

  • :log info "tekst" - log
  • :put "tekst" - wyświetl
  • :typeof zmienna - typ zmiennej
  • :len kolekcja - długość

Dodatek zawierający listę wszystkich przydatnych poleceń skryptowych RouterOS stanowi praktyczną ściągawkę do szybkiego odwołania podczas codziennej pracy. Deklaracje zmiennych lokalnych i globalnych za pomocą `:local` i `:global`, modyfikacja wartości przez `:set` oraz sprawdzanie typu przez `:typeof` to podstawowe operacje, które pojawiają się w każdym skrypcie. Sterowanie przebiegiem kodu realizują instrukcje `:if`, `:for`, `:foreach` i `:while`, które wspólnie pokrywają wszystkie potrzeby związane z warunkami i pętlami.

Polecenia systemowe, takie jak `:log` do zapisywania komunikatów w logach, `:put` do wyświetlania tekstu w konsoli oraz `:len` do sprawdzania długości kolekcji, uzupełniają zestaw podstawowych narzędzi każdego skryptera. Wiedza o tym, jakie polecenia są dostępne i jak je poprawnie stosować, jest fundamentem samodzielnego tworzenia skryptów. Zaleca się wydrukowanie tej ściągawki i trzymanie jej w widocznym miejscu podczas pierwszych prób pisania własnego kodu, co znacznie przyspieszy proces nauki i zmniejszy liczbę popełnianych błędów.

52Dodatek: Operacje na tablicach - podsumowanie

Funkcje do pracy z tablicami i kolekcjami

  • Tworzenie: :local arr {1, 2, 3}
  • Dodawanie: :set ($arr->index) wartosc
  • Pobieranie: :pick $arr index
  • Długość: [:len $arr]
  • Pusta tablica: [:toarray ""]

Iteracja:

# --- Tworzenie i operacje na tablicach ---

# Tablica liczb
:local liczby {10, 20, 30, 40, 50}

# Pobierz elementy
:put ("Pierwszy: " . [:pick $liczby 0])     # 10
:put ("Ostatni: " . [:pick $liczby ([:len $liczby] - 1)])  # 50

# Modyfikuj element
:set ($liczby->2) 35
:put ("Trzeci po modyfikacji: " . [:pick $liczby 2])  # 35

# Dodaj nowy element
:set ($liczby->5) 60

# Iteruj przez wszystkie
:foreach liczba in=$liczby do={
    :put ("Element: " . $liczba)
}

# Filtrowanie tablicy (symulacja)
:local parzyste {}
:foreach liczba in=$liczby do={
    :if (($liczba % 2) = 0) do={
        :set ($parzyste->[:len $parzyste]) $liczba
    }
}
:put ("Parzyste: " . $parzyste)

Dodatek dotyczący operacji na tablicach w RouterOS podsumowuje wszystkie funkcje i techniki związane z przetwarzaniem kolekcji danych. Tworzenie tablicy za pomocą nawiasów klamrowych `{1, 2, 3}` oraz dostęp do elementów przez `:pick` to podstawowe operacje, które każdy skrypter powinien opanować na pamięć. Dynamiczne dodawanie elementów przez `:set ($tablica->indeks) wartosc` oraz sprawdzanie długości kolekcji za pomocą `:len` pozwalają na elastyczne zarządzanie danymi w trakcie wykonywania skryptu.

Iteracja po wszystkich elementach tablicy w pętli `:foreach` oraz symulacja filtrowania przez połączenie pętli z instrukcją warunkową `:if` umożliwiają realizację zaawansowanych operacji na danych bez potrzeby używania zewnętrznych narzędzi. Mimo że RouterOS nie oferuje wbudowanych funkcji sortowania tablic, można to zaimplementować ręcznie za pomocą algorytmu bąbelkowego lub przez wykorzystanie zewnętrznych skryptów. Praktyczne przykłady zawarte w tym dodatku pokazują najczęstsze wzorce użycia tablic w codziennej administracji MikroTik.

53Dodatek: Sposoby uruchamiania skryptów

Metody uruchamiania skryptów w RouterOS

  1. Ręcznie z terminala:
    /system script run nazwa_skryptu
  2. Przez Scheduler:
    /system scheduler add name=codziennie interval=1d on-event=nazwa_skryptu
  3. Przez Netwatch:
    Skrypt uruchamia się automatycznie gdy host zmieni stan
  4. Przez Event Scheduler (RouterOS v7+):
    Uruchomienie w odpowiedzi na zdarzenie systemowe
  5. Przy starcie systemu:
    /system scheduler add name=startup on-event=nazwa policy=read,write start-time=startup

Uprawnienia skryptów (policy)

Skrypty mogą wymagać określonych uprawnień: read, write, test, policy, sniff, sensitive, ftp, reboot, write, etc.

Domyślne uprawnienia dla scheduler ustawia się w parametrze policy.

# --- Przykladowe konfiguracje scheduler ---

# Codziennie o północy
/system scheduler add name=daily-backup interval=1d \
    on-event=backup policy=read,write,test start-time=00:00:00

# Co godzinę
/system scheduler add name=hourly-check interval=1h \
    on-event=sprawdz-interfejsy policy=read,write

# Co 5 minut
/system scheduler add name=frequent interval=5m \
    on-event=monitoring policy=read

# Jednorazowo, za 10 minut
/system scheduler add name=once interval=10m \
    on-event=jednorazowy-skrypt policy=read,write

# Przy starcie routera
/system scheduler add name=on-boot interval=0 \
    on-event=konfiguracja-początkowa policy=read,write,reboot \
    start-time=startup

Dodatek opisujący sposoby uruchamiania skryptów w RouterOS zestawia wszystkie dostępne metody w jednym miejscu, ułatwiając wybór odpowiedniej techniki dla konkretnego zastosowania. Ręczne uruchamianie przez `/system script run` jest najprostszą metodą, idealną do testowania i jednorazowych zadań. Scheduler zapewnia automatyczne, cykliczne wykonywanie skryptów o zadanych interwałach, co jest podstawą automatyzacji codziennych zadań administracyjnych. Netwatch uruchamia skrypty w odpowiedzi na zmiany stanu monitorowanych hostów, co pozwala na szybką reakcję na zdarzenia sieciowe.

Bardziej zaawansowane metody obejmują uruchamianie przez Event Scheduler dostępny w RouterOS w wersji 7, który reaguje na konkretne zdarzenia systemowe, oraz uruchamianie przy starcie systemu za pomocą schedulera z parametrem `start-time=startup`. Każda z tych metod ma swoje zalety i ograniczenia, a wybór odpowiedniej zależy od konkretnego przypadku użycia. Parametr `policy` przy konfiguracji schedulera określa uprawnienia, z jakimi skrypt będzie wykonywany, co ma wpływ na dostęp do zasobów systemu i powinno być starannie dobrane dla zachowania bezpieczeństwa.

54Dodatek: Przykładowy harmonogram zadań

Typowy zestaw skryptów do regularnego uruchamiania

Oto przykładowy zestaw skryptów, który możesz mieć na produkcyjnym routerze:

Skrypt Częstotliwość Cel
backup-konfiguracji 1x dziennie Kopia zapasowa
aktualizacja-ddns Co 30 min Aktualizacja DNS
sprawdz-failover Co 1 min Monitoring łącza
blokuj-atakujacych Co 5 min Ochrona SSH
czysczenie-logow 1x dziennie Czyszczenie logów

Dodatek zawierający przykładowy harmonogram zadań dla produkcyjnego routera MikroTik prezentuje typowy zestaw skryptów, które powinny być regularnie uruchamiane w środowisku sieciowym. Codzienne zadania, takie jak tworzenie kopii zapasowych konfiguracji i czyszczenie starych logów, są zwykle wykonywane raz na dobę w godzinach nocnych, aby nie obciążać routera w szczycie aktywności użytkowników. Zadania monitorujące, takie jak aktualizacja DDNS co 30 minut czy sprawdzanie failover co minutę, wymagają częstszego uruchamiania, aby zapewnić szybką reakcję na zmieniające się warunki sieciowe.

Skrypt ochrony SSH przed atakami brute-force powinien być uruchamiany co 5 minut, co stanowi dobry kompromis między szybkością reakcji a obciążeniem systemu. Wszystkie skrypty powinny być skonfigurowane z odpowiednimi uprawnieniami w parametrze `policy`, aby miały dostęp do niezbędnych zasobów bez nadmiernego rozszerzania uprawnień. Regularne przeglądanie i aktualizowanie harmonogramu zadań w miarę zmieniających się potrzeb sieci to dobra praktyka, która zapewnia optymalne działanie infrastruktury przy minimalnym nakładzie pracy administracyjnej.

55Dodatek: Słownik pojęć

Pojęcia związane ze skryptowaniem RouterOS

  • CLI (Command Line Interface) - tekstowy interfejs zarządzania routerem
  • Zmienna - nazwany pojemnik na dane
  • Zmienna lokalna - istnieje tylko podczas jednego uruchomienia skryptu
  • Zmienna globalna - istnieje w całym systemie
  • Tablica (array) - zbiór wielu wartości pod jedną nazwą
  • Iteracja - jedno przejście pętli
  • Konkatenacja - łączenie tekstów
  • Operator - symbol wykonujący operację (+, -, =, itd.)
  • Warunek - wyrażenie, które jest prawdziwe lub fałszywe
  • Debugowanie - szukanie i naprawianie błędów w kodzie
  • Scheduler - harmonogram automatycznego uruchamiania skryptów
  • Netwatch - narzędzie monitorujące dostępność hostów
  • DDNS - Dynamiczny DNS, usługa mapująca zmienne IP na stałe nazwy domenowe
  • Failover - automatyczne przełączenie na zapasowe łącze
  • Backup - kopia zapasowa konfiguracji

Słownik pojęć w dodatku zawiera definicje kluczowych terminów związanych ze skryptowaniem w RouterOS, które każdy administrator powinien znać i rozumieć. CLI to tekstowy interfejs zarządzania routerem umożliwiający wydawanie poleceń i pisanie skryptów. Zmienna to nazwany pojemnik na dane, który może przechowywać wartości różnych typów, od prostych liczb po złożone tablice. Zmienna lokalna istnieje tylko podczas jednego uruchomienia skryptu, natomiast globalna zachowuje swoją wartość w systemie między uruchomieniami, co pozwala na współdzielenie stanu między skryptami.

Tablica to struktura danych przechowująca wiele wartości pod jedną nazwą z dostępem przez indeks numeryczny. Iteracja oznacza jedno przejście pętli przez element kolekcji, a konkatenacja to łączenie tekstów za pomocą operatora `.`. Operator to symbol wykonujący operację na danych, a warunek to wyrażenie logiczne zwracające prawdę lub fałsz. Debugowanie to proces szukania i naprawiania błędów, niezbędny przy tworzeniu niezawodnych skryptów. Scheduler, Netwatch, DDNS, Failover i Backup to narzędzia i mechanizmy, które w połączeniu z językiem skryptowym tworzą kompletne środowisko do automatyzacji zarządzania sieciami opartymi na RouterOS.