Compare commits

..

No commits in common. "main" and "change-138" have entirely different histories.

130 changed files with 317 additions and 804 deletions

View file

@ -61,7 +61,7 @@ Import a certificate by CommonName
Running the function `$CertificateAvailable` with that name as parameter
makes sure the certificate is available in the device's store:
$CertificateAvailable "ISRG Root X2" "fetch";
$CertificateAvailable "ISRG Root X2";
If the certificate is actually available already nothing happens, and there
is no output. Otherwise the certificate is downloaded and imported.

View file

@ -35,7 +35,6 @@ Add yourself to the list,
[donate with PayPal ↗️](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)!
* Abdul Mannan Abbasi
* Alex Maier
* Andrea Ruffini Perico
* Andrew Cox
* Christoph Boss (@Kampfwurst)

View file

@ -17,16 +17,10 @@ Initial commands
Run the complete base installation:
{
:local BaseUrl "https://rsc.eworm.de/main/";
:local CertCommonName "ISRG Root X2";
:local BaseUrl "https://git.eworm.de/cgit/routeros-scripts/plain/";
:local CertFileName "ISRG-Root-X2.pem";
:local CertFingerprint "69729b8e15a86efc177a57afb7171dfc64add28c2fca8cf1507e34453ccb1470";
:local CertSettings [ /certificate/settings/get ];
:if (!((($CertSettings->"builtin-trust-anchors") = "trusted" || \
($CertSettings->"builtin-trust-store") ~ "fetch" || \
($CertSettings->"builtin-trust-store") = "all") && \
[[ :parse (":return [ :len [ /certificate/builtin/find where common-name=\"" . $CertCommonName . "\" ] ]") ]] > 0)) do={
:put "Importing certificate...";
/tool/fetch ($BaseUrl . "certs/" . $CertFileName) dst-path=$CertFileName as-value;
:delay 1s;
@ -35,22 +29,22 @@ Run the complete base installation:
:error "Something is wrong with your certificates!";
};
:delay 1s;
};
:put "Renaming global-config-overlay, if exists...";
/system/script/set name=("global-config-overlay-" . [ /system/clock/get date ] . "-" . [ /system/clock/get time ]) [ find where name="global-config-overlay" ];
:foreach Script in={ "global-config"; "global-config-overlay"; "global-functions" } do={
:put "Installing $Script...";
/system/script/remove [ find where name=$Script ];
/system/script/add name=$Script owner=$Script source=([ /tool/fetch check-certificate=yes-without-crl ($BaseUrl . $Script . ".rsc") output=user as-value ]->"data");
/system/script/add name=$Script owner=$Script source=([ /tool/fetch check-certificate=yes-without-crl ($BaseUrl . $Script . ".rsc") output=user as-value]->"data");
};
:put "Loading configuration and functions...";
/system/script { run global-config; run global-functions; };
:if ([ :len [ /certificate/find where fingerprint=$CertFingerprint ] ] > 0) do={
:put "Scheduling to load configuration and functions...";
/system/scheduler/remove [ find where name="global-scripts" ];
/system/scheduler/add name="global-scripts" start-time=startup on-event="/system/script { run global-config; run global-functions; }";
:put "Renaming certificate by its common-name...";
:global CertificateNameByCN;
$CertificateNameByCN $CertFingerprint;
};
};
Then continue setup with
[scheduled automatic updates](README.md#scheduled-automatic-updates) or

View file

@ -2,45 +2,38 @@
# template scripts -> final scripts
# markdown files -> html files
ALL_RSC := $(wildcard *.rsc */*.rsc)
GEN_RSC := $(wildcard *.capsman.rsc *.local.rsc *.wifi.rsc)
CAPSMAN = $(wildcard *.capsman.rsc)
LOCAL = $(wildcard *.local.rsc)
WIFI = $(wildcard *.wifi.rsc)
MARKDOWN := $(wildcard *.md doc/*.md doc/mod/*.md)
HTML := $(MARKDOWN:.md=.html)
MARKDOWN = $(wildcard *.md doc/*.md doc/mod/*.md)
HTML = $(MARKDOWN:.md=.html)
DATE ?= $(shell date --rfc-email)
VERSION ?= $(shell git symbolic-ref --short HEAD 2>/dev/null)/$(shell git rev-list --count HEAD 2>/dev/null)/$(shell git rev-parse --short=8 HEAD 2>/dev/null)
export DATE VERSION
all: $(CAPSMAN) $(LOCAL) $(WIFI) $(HTML) checksums.json
.PHONY: all checksums commitinfo docs rsc clean
%.html: %.md Makefile
markdown $< | sed 's/href="\([-_\./[:alnum:]]*\)\.md"/href="\1.html"/g' > $@
all: checksums docs rsc
%.capsman.rsc: %.template.rsc Makefile
sed -e '/\/interface\/wifi\//d' -e '/\/interface\/wireless\//d' -e 's|%TEMPL%|.capsman|' \
-e '/^# NOT \/caps-man\/ #$$/,/^# NOT \/caps-man\/ #$$/d' \
-e '/^# !!/,/^# !!/c # !! Do not edit this file, it is generated from template!' \
< $< > $@
checksums: checksums.json
%.local.rsc: %.template.rsc Makefile
sed -e '/\/caps-man\//d' -e '/\/interface\/wifi\//d' -e 's|%TEMPL%|.local|' \
-e '/^# NOT \/interface\/wireless\/ #$$/,/^# NOT \/interface\/wireless\/ #$$/d' \
-e '/^# !!/,/^# !!/c # !! Do not edit this file, it is generated from template!' \
< $< > $@
checksums.json: contrib/checksums.sh $(ALL_RSC)
contrib/checksums.sh > $@
%.wifi.rsc: %.template.rsc Makefile
sed -e '/\/caps-man\//d' -e '/\/interface\/wireless\//d' -e 's|%TEMPL%|.wifi|' \
-e '/^# NOT \/interface\/wifi\/ #$$/,/^# NOT \/interface\/wifi\/ #$$/d' \
-e '/^# !!/,/^# !!/c # !! Do not edit this file, it is generated from template!' \
< $< > $@
commitinfo: global-functions.rsc
contrib/commitinfo.sh $< > $<~
mv $<~ $<
docs: $(HTML)
%.html: %.md general/style.css contrib/html.sh contrib/html.sh.d/head.html contrib/html.sh.d/foot.html
contrib/html.sh $< > $@
rsc: $(GEN_RSC)
%.capsman.rsc: %.template.rsc contrib/template-capsman.sh
contrib/template-capsman.sh $< > $@
%.local.rsc: %.template.rsc contrib/template-local.sh
contrib/template-local.sh $< > $@
%.wifi.rsc: %.template.rsc contrib/template-wifi.sh
contrib/template-wifi.sh $< > $@
checksums.json: contrib/checksums.sh *.rsc */*.rsc
contrib/checksums.sh
clean:
rm -f $(HTML) checksums.json
make -C contrib/ clean

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6 KiB

After

Width:  |  Height:  |  Size: 5 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 207 B

After

Width:  |  Height:  |  Size: 207 B

Before After
Before After

View file

@ -55,18 +55,15 @@ Initial setup
### Get me ready!
If you know how things work just copy and paste the
[initial commands](INITIAL-COMMANDS.md). These also support fixing an
existing but broken installation. Remember to edit and rerun
[initial commands](INITIAL-COMMANDS.md). Remember to edit and rerun
`global-config-overlay`!
> 💡️ **Hint**: First time users should take
> [the long way in detail](#the-long-way-in-detail) below.
First time users should take the long way below.
### Live presentation
Want to see it in action? I've had a presentation [Repository based
RouterOS script distribution ↗️](https://www.youtube.com/watch?v=B9neG3oAhcY)
including demonstration recorded live at [MUM Europe
including demonstation recorded live at [MUM Europe
2019 ↗️](https://mum.mikrotik.com/2019/EU/) in Vienna.
> ⚠️ **Warning**: Some details changed. So see the presentation, then follow
@ -75,22 +72,11 @@ including demonstration recorded live at [MUM Europe
### The long way in detail
The update script does server certificate verification, so first step is to
download the certificates.
> 💡️ **Hint**: RouterOS 7.19 comes with a builtin certificate store. You
> can skip the steps regarding certificate download and import and jump
> to [installation of scripts](#installation-of-scripts) if you set the
> trust for these builtin trust anchors:
> `/certificate/settings/set builtin-trust-anchors=trusted;`
> With RouterOS 7.21 the functionality was changed. Set this at minimum,
> but make sure not to drop other targets:
> `/certificate/settings/set builtin-trust-store=fetch;`
If you intend to download the scripts from a
download the certificates. If you intend to download the scripts from a
different location (for example from github.com) install the corresponding
certificate chain.
/tool/fetch "https://rsc.eworm.de/main/certs/ISRG-Root-X2.pem" dst-path="isrg-root-x2.pem";
/tool/fetch "https://git.eworm.de/cgit/routeros-scripts/plain/certs/ISRG-Root-X2.pem" dst-path="isrg-root-x2.pem";
![screenshot: download certs](README.d/01-download-certs.avif)
@ -120,24 +106,22 @@ is shown.
Always make sure there are no certificates installed you do not know or want!
#### Installation of scripts
All following commands will verify the server certificate. For validity the
certificate's lifetime is checked with local time, so make sure the device's
date and time is set correctly!
Now let's download the main scripts and add them in configuration on the fly.
:foreach Script in={ "global-config"; "global-config-overlay"; "global-functions" } do={ /system/script/add name=$Script owner=$Script source=([ /tool/fetch check-certificate=yes-without-crl ("https://rsc.eworm.de/main/" . $Script . ".rsc") output=user as-value ]->"data"); };
:foreach Script in={ "global-config"; "global-config-overlay"; "global-functions" } do={ /system/script/add name=$Script owner=$Script source=([ /tool/fetch check-certificate=yes-without-crl ("https://git.eworm.de/cgit/routeros-scripts/plain/" . $Script . ".rsc") output=user as-value]->"data"); };
![screenshot: import scripts](README.d/04-import-scripts.avif)
And finally run configuration and functions. This will also add the
scheduler for loading at system startup automatically.
And finally load configuration and functions and add the scheduler.
/system/script { run global-config; run global-functions; };
/system/scheduler/add name="global-scripts" start-time=startup on-event="/system/script { run global-config; run global-functions; }";
![screenshot: run scripts](README.d/05-run-scripts.avif)
![screenshot: run and schedule scripts](README.d/05-run-and-schedule-scripts.avif)
> 💡️ **Hint**: You see complaints regarding syntax errors? Most likely the
> RouterOS on your device is too old. Check for updates!
@ -225,7 +209,7 @@ cleanup add a scheduler entry.
$ScriptInstallUpdate dhcp-to-dns,lease-script;
/ip/dhcp-server/set lease-script=lease-script [ find ];
/system/scheduler/add name="dhcp-to-dns" interval=5m start-time=startup on-event="/system/script/run dhcp-to-dns;";
/system/scheduler/add name="dhcp-to-dns" interval=5m on-event="/system/script/run dhcp-to-dns;";
![screenshot: setup lease script](README.d/12-setup-lease-script.avif)
@ -407,15 +391,14 @@ immediately remove the link in question.
Upstream
--------
[rsc.eworm.de](https://rsc.eworm.de/)
[![upstream](README.d/upstream.png)](https://rsc.eworm.de/)
[![upstream](general/qr-code.png)](https://rsc.eworm.de/)
URL:
[GitHub.com](https://github.com/eworm-de/routeros-scripts#routeros-scripts)
### Code hosting
* [git.eworm.de](https://git.eworm.de/cgit/routeros-scripts/about/)
* [GitHub.com](https://github.com/eworm-de/routeros-scripts#routeros-scripts)
* [GitLab.com](https://gitlab.com/eworm-de/routeros-scripts#routeros-scripts)
Mirror:
[eworm.de](https://git.eworm.de/cgit/routeros-scripts/about/)
[GitLab.com](https://gitlab.com/eworm-de/routeros-scripts#routeros-scripts)
---
[⬆️ Go back to top](#top)

View file

@ -22,7 +22,7 @@
:foreach AccList in=[ /caps-man/access-list/find where mac-address!="00:00:00:00:00:00" ] do={
:local Mac [ /caps-man/access-list/get $AccList mac-address ];
:if ($Seen->$Mac = 1) do={
/caps-man/access-list/print without-paging where mac-address=$Mac;
/caps-man/access-list/print where mac-address=$Mac;
:local Remove [ :tonum [ /terminal/ask prompt="\nNumeric id to remove, any key to skip!" ] ];
:if ([ :typeof $Remove ] = "num") do={

View file

@ -22,7 +22,7 @@
:foreach AccList in=[ /interface/wireless/access-list/find where mac-address!="00:00:00:00:00:00" ] do={
:local Mac [ /interface/wireless/access-list/get $AccList mac-address ];
:if ($Seen->$Mac = 1) do={
/interface/wireless/access-list/print without-paging where mac-address=$Mac;
/interface/wireless/access-list/print where mac-address=$Mac;
:local Remove [ :tonum [ /terminal/ask prompt="\nNumeric id to remove, any key to skip!" ] ];
:if ([ :typeof $Remove ] = "num") do={

View file

@ -27,9 +27,9 @@
:local Mac [ /interface/wifi/access-list/get $AccList mac-address ];
:local Mac [ /interface/wireless/access-list/get $AccList mac-address ];
:if ($Seen->$Mac = 1) do={
/caps-man/access-list/print without-paging where mac-address=$Mac;
/interface/wifi/access-list/print without-paging where mac-address=$Mac;
/interface/wireless/access-list/print without-paging where mac-address=$Mac;
/caps-man/access-list/print where mac-address=$Mac;
/interface/wifi/access-list/print where mac-address=$Mac;
/interface/wireless/access-list/print where mac-address=$Mac;
:local Remove [ :tonum [ /terminal/ask prompt="\nNumeric id to remove, any key to skip!" ] ];
:if ([ :typeof $Remove ] = "num") do={

View file

@ -22,7 +22,7 @@
:foreach AccList in=[ /interface/wifi/access-list/find where mac-address!="00:00:00:00:00:00" ] do={
:local Mac [ /interface/wifi/access-list/get $AccList mac-address ];
:if ($Seen->$Mac = 1) do={
/interface/wifi/access-list/print without-paging where mac-address=$Mac;
/interface/wifi/access-list/print where mac-address=$Mac;
:local Remove [ :tonum [ /terminal/ask prompt="\nNumeric id to remove, any key to skip!" ] ];
:if ([ :typeof $Remove ] = "num") do={

View file

@ -27,7 +27,6 @@
:global CleanName;
:global DeviceInfo;
:global FileExists;
:global FormatLine;
:global LogPrint;
:global MkDir;
@ -125,19 +124,17 @@
attach=$Attach; remove-attach=true });
# wait for the mail to be sent
:do {
:retry {
:if ([ $FileExists ($FilePath . ".conf") ".conf file" ] = true || \
[ $FileExists ($FilePath . ".backup") "backup" ] = true || \
[ $FileExists ($FilePath . ".rsc") "script" ] = true) do={
:error "Files are still available.";
}
} delay=1s max=120;
} on-error={
:local I 0;
:while ([ :len [ /file/find where name ~ ($FilePath . "\\.(backup|rsc)\$") ] ] > 0) do={
:if ($I >= 120) do={
$LogPrint warning $ScriptName ("Files are still available, sending e-mail failed.");
:set PackagesUpdateBackupFailure true;
:set ExitOK true;
:error false;
}
:delay 1s;
:set I ($I + 1);
}
# do not remove the files here, as the mail is still queued!
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
}

View file

@ -20,7 +20,6 @@
:global CleanFilePath;
:global DownloadPackage;
:global FileGet;
:global LogPrint;
:global MkDir;
:global RmFile;
@ -43,7 +42,7 @@
:error false;
}
:if ([ $FileGet $PackagePath ] = false) do={
:if ([ :len [ /file/find where name=$PackagePath type="directory" ] ] = 0) do={
:if ([ $MkDir $PackagePath ] = false) do={
$LogPrint warning $ScriptName ("Creating directory at CAPsMAN package path (" . \
$PackagePath . ") failed!");
@ -54,7 +53,7 @@
"). Please place your packages!");
}
:foreach Package in=[ /file/find where type="package" \
:foreach Package in=[ /file/find where type=package \
package-version!=$InstalledVersion name~("^" . $PackagePath) ] do={
:local File [ /file/get $Package ];
:if ($File->"package-architecture" = "mips") do={
@ -67,7 +66,7 @@
}
}
:if ([ :len [ /file/find where type="package" name~("^" . $PackagePath) ] ] = 0) do={
:if ([ :len [ /file/find where type=package name~("^" . $PackagePath) ] ] = 0) do={
$LogPrint info $ScriptName ("No packages available, downloading default set.");
:foreach Arch in={ "arm"; "mipsbe" } do={
:foreach Package in={ "routeros"; "wireless" } do={

View file

@ -21,7 +21,6 @@
:global CleanFilePath;
:global DownloadPackage;
:global FileGet;
:global LogPrint;
:global MkDir;
:global RmFile;
@ -45,7 +44,7 @@
:error false;
}
:if ([ $FileGet $PackagePath ] = false) do={
:if ([ :len [ /file/find where name=$PackagePath type="directory" ] ] = 0) do={
:if ([ $MkDir $PackagePath ] = false) do={
$LogPrint warning $ScriptName ("Creating directory at CAPsMAN package path (" . \
$PackagePath . ") failed!");
@ -56,7 +55,7 @@
"). Please place your packages!");
}
:foreach Package in=[ /file/find where type="package" \
:foreach Package in=[ /file/find where type=package \
package-version!=$InstalledVersion name~("^" . $PackagePath) ] do={
:local File [ /file/get $Package ];
:if ($File->"package-architecture" = "mips") do={
@ -69,7 +68,7 @@
}
}
:if ([ :len [ /file/find where type="package" name~("^" . $PackagePath) ] ] = 0) do={
:if ([ :len [ /file/find where type=package name~("^" . $PackagePath) ] ] = 0) do={
$LogPrint info $ScriptName ("No packages available, downloading default set.");
# NOT /interface/wifi/ #
:foreach Arch in={ "arm"; "mipsbe" } do={

View file

@ -20,7 +20,6 @@
:global CleanFilePath;
:global DownloadPackage;
:global FileGet;
:global LogPrint;
:global MkDir;
:global RmFile;
@ -43,7 +42,7 @@
:error false;
}
:if ([ $FileGet $PackagePath ] = false) do={
:if ([ :len [ /file/find where name=$PackagePath type="directory" ] ] = 0) do={
:if ([ $MkDir $PackagePath ] = false) do={
$LogPrint warning $ScriptName ("Creating directory at CAPsMAN package path (" . \
$PackagePath . ") failed!");
@ -54,7 +53,7 @@
"). Please place your packages!");
}
:foreach Package in=[ /file/find where type="package" \
:foreach Package in=[ /file/find where type=package \
package-version!=$InstalledVersion name~("^" . $PackagePath) ] do={
:local File [ /file/get $Package ];
:if ($File->"package-architecture" = "mips") do={
@ -67,7 +66,7 @@
}
}
:if ([ :len [ /file/find where type="package" name~("^" . $PackagePath) ] ] = 0) do={
:if ([ :len [ /file/find where type=package name~("^" . $PackagePath) ] ] = 0) do={
$LogPrint info $ScriptName ("No packages available, downloading default set.");
:foreach Arch in={ "arm"; "arm64" } do={
:local Packages { "arm"={ "routeros"; "wifi-qcom"; "wifi-qcom-ac" };

View file

@ -21,7 +21,7 @@
:global CertWarnTime;
:global Identity;
:global CertificateAvailable;
:global CertificateAvailable
:global EscapeForRegEx;
:global IfThenElse;
:global LogPrint;
@ -189,7 +189,7 @@
fingerprint!=[ :tostr ($CertVal->"fingerprint") ] expires-after>$CertRenewTime ];
:local CertNewVal [ /certificate/get $CertNew ];
:if ([ $CertificateAvailable ([ $ParseKeyValueStore ($CertNewVal->"issuer") ]->"CN") "fetch" ] = false) do={
:if ([ $CertificateAvailable ([ $ParseKeyValueStore ($CertNewVal->"issuer") ]->"CN") ] = false) do={
$LogPrint warning $ScriptName ("The certificate chain is not available!");
}
@ -231,7 +231,7 @@
:local State [ $IfThenElse (($CertVal->"expired") = true) "expired" "is about to expire" ];
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "lock-with-ink-pen,warning-sign" ] . "Certificate warning: " . ($CertVal->"name")); \
subject=([ $SymbolForNotification "warning-sign" ] . "Certificate warning: " . ($CertVal->"name")); \
message=("A certificate on " . $Identity . " " . $State . ".\n\n" . [ $FormatInfo $Cert ]) });
$LogPrint info $ScriptName ("The certificate '" . ($CertVal->"name") . "' " . $State . \
", it is invalid after " . ($CertVal->"invalid-after") . ".");

View file

@ -12,7 +12,6 @@
:set ($CheckHealthPlugins->[ :jobname ]) do={
:local FuncName [ :tostr $0 ];
:local ScriptName [ :tostr $1 ];
:global CheckHealthLast;
:global Identity;
@ -33,13 +32,13 @@
:if ([ :typeof ($CheckHealthLast->$Name) ] != "nothing") do={
:if ($CheckHealthLast->$Name = "ok" && \
$Value != "ok") do={
$SendNotification2 ({ origin=$ScriptName; \
$SendNotification2 ({ origin=$FuncName; \
subject=([ $SymbolForNotification "cross-mark" ] . "Health warning: " . $Name); \
message=("The device '" . $Name . "' on " . $Identity . " failed!") });
}
:if ($CheckHealthLast->$Name != "ok" && \
$Value = "ok") do={
$SendNotification2 ({ origin=$ScriptName; \
$SendNotification2 ({ origin=$FuncName; \
subject=([ $SymbolForNotification "white-heavy-check-mark" ] . "Health recovery: " . $Name); \
message=("The device '" . $Name . "' on " . $Identity . " recovered!") });
}

View file

@ -12,7 +12,6 @@
:set ($CheckHealthPlugins->[ :jobname ]) do={
:local FuncName [ :tostr $0 ];
:local ScriptName [ :tostr $1 ];
:global CheckHealthLast;
:global CheckHealthTemperature;
@ -55,7 +54,7 @@
}
:if ($Value > $CheckHealthTemperature->$Name && \
$CheckHealthTemperatureNotified->$Name != true) do={
$SendNotification2 ({ origin=$ScriptName; \
$SendNotification2 ({ origin=$FuncName; \
subject=([ $SymbolForNotification "fire" ] . "Health warning: " . $Name); \
message=("The " . $Name . " on " . $Identity . " is above threshold: " . \
$Value . "\C2\B0" . "C") });
@ -63,7 +62,7 @@
}
:if ($Value <= ($CheckHealthTemperature->$Name - $CheckHealthTemperatureDeviation) && \
$CheckHealthTemperatureNotified->$Name = true) do={
$SendNotification2 ({ origin=$ScriptName; \
$SendNotification2 ({ origin=$FuncName; \
subject=([ $SymbolForNotification "white-heavy-check-mark" ] . "Health recovery: " . $Name); \
message=("The " . $Name . " on " . $Identity . " dropped below threshold: " . \
$Value . "\C2\B0" . "C") });

View file

@ -12,7 +12,6 @@
:set ($CheckHealthPlugins->[ :jobname ]) do={
:local FuncName [ :tostr $0 ];
:local ScriptName [ :tostr $1 ];
:global CheckHealthLast;
:global CheckHealthVoltageLow;
@ -40,7 +39,7 @@
:if ($NumLast * (100 + $CheckHealthVoltagePercent) < $NumCurr * 100 || \
$NumLast * 100 > $NumCurr * (100 + $CheckHealthVoltagePercent)) do={
$SendNotification2 ({ origin=$ScriptName; \
$SendNotification2 ({ origin=$FuncName; \
subject=([ $SymbolForNotification ("high-voltage-sign,chart-" . [ $IfThenElse ($NumLast < \
$NumCurr) "in" "de" ] . "creasing") ] . "Health warning: " . $Name); \
message=("The " . $Name . " on " . $Identity . " jumped more than " . $CheckHealthVoltagePercent . "%.\n\n" . \
@ -48,12 +47,12 @@
[ $FormatLine "new value" ($Value . " V") 12 ]) });
} else={
:if ($NumCurr <= $CheckHealthVoltageLow && $NumLast > $CheckHealthVoltageLow) do={
$SendNotification2 ({ origin=$ScriptName; \
$SendNotification2 ({ origin=$FuncName; \
subject=([ $SymbolForNotification "high-voltage-sign,chart-decreasing" ] . "Health warning: Low " . $Name); \
message=("The " . $Name . " on " . $Identity . " dropped to " . $Value . " V below hard limit.") });
}
:if ($NumCurr > $CheckHealthVoltageLow && $NumLast <= $CheckHealthVoltageLow) do={
$SendNotification2 ({ origin=$ScriptName; \
$SendNotification2 ({ origin=$FuncName; \
subject=([ $SymbolForNotification "high-voltage-sign,chart-increasing" ] . "Health recovery: Low " . $Name); \
message=("The " . $Name . " on " . $Identity . " recovered to " . $Value . " V above hard limit.") });
}

View file

@ -92,16 +92,16 @@
:onerror Err {
/system/script/run $Plugin;
} do={
$LogPrint error $ScriptName ("Plugin '" . $PluginVal->"name" . "' failed to run: " . $Err);
$LogPrint error $ScriptName ("Plugin '" . $ScriptVal->"name" . "' failed to run: " . $Err);
}
} else={
$LogPrint error $ScriptName ("Plugin '" . $PluginVal->"name" . "' failed syntax validation, skipping.");
$LogPrint error $ScriptName ("Plugin '" . $ScriptVal->"name" . "' failed syntax validation, skipping.");
}
}
:foreach PluginName,Discard in=$CheckHealthPlugins do={
($CheckHealthPlugins->$PluginName) \
("\$CheckHealthPlugins->\"" . $PluginName . "\"") $ScriptName;
("\$CheckHealthPlugins->\"" . $PluginName . "\"");
}
:set CheckHealthPlugins;

View file

@ -42,7 +42,7 @@
$LogPrint warning $ScriptName ("Your license expired on " . ($License->"deadline-at") . "!");
:if ($SentCertificateNotification != "expired") do={
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "scroll,cross-mark" ] . "License expired!"); \
subject=([ $SymbolForNotification "warning-sign" ] . "License expired!"); \
message=("Your license expired on " . ($License->"deadline-at") . \
", can no longer update RouterOS on " . $Identity . "...") });
:set SentCertificateNotification "expired";
@ -55,7 +55,7 @@
$LogPrint warning $ScriptName ("Your license will expire on " . ($License->"deadline-at") . "!");
:if ($SentCertificateNotification != "warning") do={
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "scroll,warning-sign" ] . "License about to expire!"); \
subject=([ $SymbolForNotification "warning-sign" ] . "License about to expire!"); \
message=("Your license failed to renew and is about to expire on " . \
($License->"deadline-at") . " on " . $Identity . "...") });
:set SentCertificateNotification "warning";
@ -68,7 +68,7 @@
[ :totime ($License->"deadline-at") ] - 4w > [ :timestamp ]) do={
$LogPrint info $ScriptName ("Your license was successfully renewed.");
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "scroll,white-heavy-check-mark" ] . "License renewed"); \
subject=([ $SymbolForNotification "white-heavy-check-mark" ] . "License renewed"); \
message=("Your license was successfully renewed on " . $Identity . \
". It is now valid until " . ($License->"deadline-at") . ".") });
:set SentCertificateNotification;

View file

@ -28,7 +28,6 @@
:global EscapeForRegEx;
:global FetchUserAgentStr;
:global LogPrint;
:global RebootForUpdate;
:global ScriptFromTerminal;
:global ScriptLock;
:global SendNotification2;
@ -39,11 +38,14 @@
:local DoUpdate do={
:local ScriptName [ :tostr $1 ];
:global LogPrint;
:if ([ :len [ /system/script/find where name="packages-update" ] ] > 0) do={
/system/script/run packages-update;
} else={
/system/package/update/install without-paging;
}
$LogPrint info $ScriptName ("Waiting for system to reboot.");
}
:if ([ $ScriptLock $ScriptName ] = false) do={
@ -60,15 +62,10 @@
$WaitFullyConnected;
:if ([ :len [ /system/scheduler/find where name="_RebootForUpdate" ] ] > 0) do={
:if ([ :typeof $RebootForUpdate ] = "nothing") do={
$LogPrint info $ScriptName ("Found a stale scheduler for reboot, removing.");
/system/scheduler/remove "_RebootForUpdate";
} else={
$LogPrint info $ScriptName ("A reboot for update is already scheduled.");
:set ExitOK true;
:error false;
}
}
$LogPrint debug $ScriptName ("Checking for updates...");
/system/package/update/check-for-updates without-paging as-value;

View file

@ -1,17 +0,0 @@
# Makefile
HTML := $(shell grep -xl '<!-- static html //-->' *.html)
.PHONY: all docs clean
all: docs
badges.html: badges.md
markdown $< > $@
docs: static-html.sh $(HTML) badges.html
./static-html.sh $(HTML)
clean:
rm -f badges.html
git checkout HEAD -- $(HTML)

View file

@ -1,6 +0,0 @@
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.15-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)

View file

@ -6,4 +6,4 @@ set -e
md5sum $(find -name '*.rsc' | sort) | \
sed -e "s| \./||" -e 's|.rsc$||' | \
jq --raw-input --null-input '[ inputs | split (" ") | { (.[1]): (.[0]) }] | add'
jq --raw-input --null-input '[ inputs | split (" ") | { (.[1]): (.[0]) }] | add' > 'checksums.json'

View file

@ -1,6 +0,0 @@
#!/bin/sh
sed \
-e "/^:global CommitId/c :global CommitId \"${COMMITID:-unknown}\";" \
-e "/^:global CommitInfo/c :global CommitInfo \"${COMMITINFO:-unknown}\";" \
< "${1}"

View file

@ -1,23 +0,0 @@
#!/bin/sh
set -e
RELTO="$(dirname "${1}")"
sed \
-e "s|__TITLE__|$(head -n1 "${1}")|" \
-e "s|__GENERAL__|$(realpath --relative-to="${RELTO}" general/)|" \
-e "s|__ROOT__|$(realpath --relative-to="${RELTO}" ./)|" \
< "${0}.d/head.html"
markdown -f toc,idanchor "${1}" | sed \
-e 's/href="\([-_\./[:alnum:]]*\)\.md\(#[-[:alnum:]]*\)\?"/href="\1.html\2"/g' \
-e '/<h[1234] /s| id="\(.*\)">| id="\L\1">|' \
-e '/<h[1234] /s|-2[1789cd]-||g' -e '/<h[1234] /s|--26-amp-3b-||g' \
-e '/^<pre>/s|pre|pre class="code" onclick="CopyToClipboard(this)"|g' \
-e '/The above link may be broken on code hosting sites/s|blockquote|blockquote style="display: none;"|'
sed \
-e "s|__DATE__|${DATE:-$(date --rfc-email)}|" \
-e "s|__VERSION__|${VERSION:-unknown}|" \
< "${0}.d/foot.html"

View file

@ -1,5 +0,0 @@
<p class="foot">RouterOS Scripts documentation generated on <i>__DATE__</i> for <i>__VERSION__</i><br />
Copyright &copy; 2013-2025 Christian Hesse &lt;mail@eworm.de&gt;</p>
</body></html>

View file

@ -1,16 +0,0 @@
<!DOCTYPE html><html lang="en">
<head><meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>RouterOS Scripts :: __TITLE__</title>
<link rel="stylesheet" type="text/css" href="__GENERAL__/style.css">
<link rel="icon" type="image/png" href="__ROOT__/logo.png">
<script type="text/javascript" src="__GENERAL__/clipboard.js"></script>
</head><body>
<table><tr>
<td><img src="__GENERAL__/eworm-meadow.avif" alt="eworm on meadow" /></td>
<td><img src="__GENERAL__/qr-code.png" alt="QR code: rsc.eworm.de" /></td>
<td class="head"><span class="top">RouterOS Scripts</span><br />
<span class="bottom">a collection of scripts for MikroTik RouterOS</span></td>
</tr></table>
<hr />

View file

@ -0,0 +1,5 @@
body {
font-family: fira-sans, sans-serif;
font-size: 10pt;
background-color: transparent;
}

View file

@ -1,30 +1,14 @@
<!DOCTYPE html><html lang="en">
<!-- static html //-->
<head><meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>RouterOS Scripts :: Logo Color Changer</title>
<link rel="stylesheet" type="text/css" href="../general/style.css">
<link rel="icon" type="image/png" href="../logo.png">
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>RouterOS-Scripts Logo Color Changer</title>
<link rel="stylesheet" type="text/css" href="logo-color.d/style.css">
<script src="logo-color.d/script.js"></script>
</head><body>
</head>
<body>
<table><tr>
<td><img src="../general/eworm-meadow.avif" alt="eworm on meadow" /></td>
<td><img src="../general/qr-code.png" alt="QR code: rsc.eworm.de" /></td>
<td class="head"><span class="top">RouterOS Scripts</span><br />
<span class="bottom">a collection of scripts for MikroTik RouterOS</span></td>
</tr></table>
<hr />
<h1>Logo Color Changer</h1>
<!-- badges here //-->
<p><a href="../README.md">⬅️ Go back to main README</a></p>
<blockquote style="/* display */"><p>💡️ <strong>Hint</strong>: This site or links
on it may be broken on code hosting sites. Use
<a href="https://rsc.eworm.de/main/contrib/logo-color.html">Logo Color Changer</a>
instead.</p></blockquote>
<h1>RouterOS-Scripts Logo Color Changer</h1>
<p>You want the logo for your own notifications? But you joined the
<a href="https://t.me/routeros_scripts">Telegram Group</a> and want
@ -40,23 +24,17 @@ something that differentiates? Color it!</p>
<p>Then right-click, click "<i>Take Screenshot</i>" and finally select the
logo and download it.</p>
<p><img src="logo-color.d/browser-01.avif" alt="Screenshot Browser 01"></p>
<p><img src="logo-color.d/browser-02.avif" alt="Screenshot Browser 02"></p>
<p><img src="logo-color.d/browser-03.avif" alt="Screenshot Browser 03"></p>
<p><img src="logo-color.d/browser-01.avif" width=533 height=482 alt="Screenshot Browser 01">
<img src="logo-color.d/browser-02.avif" width=533 height=482 alt="Screenshot Browser 02">
<img src="logo-color.d/browser-03.avif" width=533 height=482 alt="Screenshot Browser 03"></p>
<p>(This example is with
<a href="https://www.mozilla.org/de/firefox/new/">Firefox</a>. The workflow
for other browsers may differ.)</p>
<p>See how to
<a href="../doc/mod/notification-telegram.md#set-a-profile-photo">Set
<a href="../../about/doc/mod/notification-telegram.md#set-a-profile-photo">Set
a profile photo</a> for your Telegram bot.</p>
<hr />
<p><a href="../README.md">⬅️ Go back to main README</a><br/>
<a href="#top">⬆️ Go back to top</a></p>
<p class="foot">Copyright &copy; 2013-2025 Christian Hesse &lt;mail@eworm.de&gt;</p>
</body></html>
</body>
</html>

View file

@ -0,0 +1,36 @@
body {
font-family: fira-sans, sans-serif;
font-size: 10pt;
background-color: transparent;
}
div.notification {
position: relative;
float: right;
width: 600px;
border: 3px outset #6c5d53;
/* border-radius: 5px; */
padding: 10px;
background-color: #e6e6e6;
}
div.content {
padding-left: 60px;
}
img.logo {
float: left;
border-radius: 50%;
}
p.heading {
margin: 0px;
font-weight: bold;
text-decoration: underline;
}
p.hint {
display: none;
}
pre {
font-family: fira-mono, monospace;
white-space: pre-wrap;
}
span.link {
color: #863600;
}

View file

@ -1,57 +1,35 @@
<!DOCTYPE html><html lang="en">
<!-- static html //-->
<head><meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>RouterOS Scripts :: Notification Generator</title>
<link rel="stylesheet" type="text/css" href="../general/style.css">
<link rel="icon" type="image/png" href="../logo.png">
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>RouterOS-Scripts Notification Generator</title>
<link rel="stylesheet" type="text/css" href="notification.d/style.css">
<script src="notification.d/script.js"></script>
</head><body>
</head>
<body>
<table><tr>
<td><img src="../general/eworm-meadow.avif" alt="eworm on meadow" /></td>
<td><img src="../general/qr-code.png" alt="QR code: rsc.eworm.de" /></td>
<td class="head"><span class="top">RouterOS Scripts</span><br />
<span class="bottom">a collection of scripts for MikroTik RouterOS</span></td>
</tr></table>
<hr />
<h1>Notification Generator</h1>
<!-- badges here //-->
<p><a href="../README.md">⬅️ Go back to main README</a></p>
<blockquote style="/* display */"><p>💡️ <strong>Hint</strong>: This site or links
on it may be broken on code hosting sites. Use
<a href="https://rsc.eworm.de/main/contrib/notification.html">Notification Generator</a>
instead.</p></blockquote>
<h1>RouterOS-Scripts Notification Generator</h1>
<div class="notification">
<img src="../logo.svg" alt="logo" class="logo" width=48 height=48>
<div class="content">
<p id="heading" class="heading">[<span id="hostname">MikroTik</span>] <span id="subject"> Subject</span></p>
<pre id="message">Message</pre>
<p id="link" class="hint">🔗 <span id="link-text" class="link">https://rsc.eworm.de/</span></p>
<p id="queued" class="hint">⏰ This message was queued since <i><span id="queued-since">2025-10-29 16:06:18</span></i> and may be obsolete.</p>
<p id="cut" class="hint">✂️ The message was too long and has been truncated, cut off <i><span id="cut-percent">13</span>%</i>!</p>
<p id="link" class="hint">🔗 <span id="link-text" class="link">https://eworm.de/</span></p>
<p id="queued" class="hint">⏰ This message was queued since <span id="queued-since">oct/18/2022 18:30:48</span> and may be obsolete.</p>
<p id="cut" class="hint">✂️ The message was too long and has been truncated, cut off <span id="cut-percent">13</span>%!</p>
</div>
</div>
<p>Hostname: <input type="text" value="MikroTik" onchange="update(this, 'hostname')"></p>
<p>Subject: <input type="text" size=50 value=" Subject" onchange="update(this, 'subject')"></p>
<p>Message: <textarea id="w3review" name="w3review" rows="4" cols="50" onchange="update(this, 'message')">Message</textarea></p>
<p><input type="checkbox" onclick="visible(this, 'link')"> Show link: <input type="text" value="https://rsc.eworm.de/" onchange="update(this, 'link-text')"></p>
<p><input type="checkbox" onclick="visible(this, 'queued')"> Queued since <input type="text" value="2025-10-29 16:06:18" onchange="update(this, 'queued-since')"></p>
<p><input type="checkbox" onclick="visible(this, 'link')"> Show link: <input type="text" value="https://eworm.de/" onchange="update(this, 'link-text')"></p>
<p><input type="checkbox" onclick="visible(this, 'queued')"> Queued since <input type="text" value="oct/18/2022 18:30:48" onchange="update(this, 'queued-since')"></p>
<p><input type="checkbox" onclick="visible(this, 'cut')"> Cut-off with <input type="number" min=1 max=99 value=13 onchange="update(this, 'cut-percent')"> percent</p>
<p>Then right-click, click "<i>Take Screenshot</i>" and finally select the
notification and download it.</p>
<hr />
<p><a href="../README.md">⬅️ Go back to main README</a><br/>
<a href="#top">⬆️ Go back to top</a></p>
<p class="foot">Copyright &copy; 2013-2025 Christian Hesse &lt;mail@eworm.de&gt;</p>
</body></html>
</body>
</html>

View file

@ -1,10 +0,0 @@
#!/bin/sh
set -e
sed -i \
-e '/href=/s|\.md|\.html|' \
-e '/blockquote/s|/\* display \*/|display: none;|' \
-e '/<!-- badges here \/\/-->/r badges.html' \
-e '/<!-- badges here \/\/-->/d' \
"${@}"

View file

@ -1,11 +0,0 @@
#!/bin/sh
set -e
sed \
-e '/\/interface\/wifi\//d' \
-e '/\/interface\/wireless\//d' \
-e 's|%TEMPL%|.capsman|' \
-e '/^# NOT \/caps-man\/ #$/,/^# NOT \/caps-man\/ #$/d' \
-e '/^# !!/,/^# !!/c # !! Do not edit this file, it is generated from template!' \
< "${1}"

View file

@ -1,11 +0,0 @@
#!/bin/sh
set -e
sed \
-e '/\/caps-man\//d' \
-e '/\/interface\/wifi\//d' \
-e 's|%TEMPL%|.local|' \
-e '/^# NOT \/interface\/wireless\/ #$/,/^# NOT \/interface\/wireless\/ #$/d' \
-e '/^# !!/,/^# !!/c # !! Do not edit this file, it is generated from template!' \
< "${1}"

View file

@ -1,11 +0,0 @@
#!/bin/sh
set -e
sed \
-e '/\/caps-man\//d' \
-e '/\/interface\/wireless\//d' \
-e 's|%TEMPL%|.wifi|' \
-e '/^# NOT \/interface\/wifi\/ #$/,/^# NOT \/interface\/wifi\/ #$/d' \
-e '/^# !!/,/^# !!/c # !! Do not edit this file, it is generated from template!' \
< "${1}"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View file

@ -19,10 +19,9 @@ Description
This script tries to download and renew certificates, then notifies about
certificates that are still about to expire.
### Sample notifications
### Sample notification
![check-certificates notification warning](check-certificates.d/notification-01-warn.avif)
![check-certificates notification renew](check-certificates.d/notification-02-renew.avif)
![check-certificates notification](check-certificates.d/notification.avif)
Requirements and installation
-----------------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View file

@ -20,10 +20,9 @@ On *Cloud Hosted Router* (*CHR*) the licensing is perpetual: Buy once, use
forever - but it needs regular renewal. This script checks licensing state
and sends a notification to warn before expiration.
### Sample notifications
### Sample notification
![check-perpetual-license notification warn](check-perpetual-license.d/notification-01-warn.avif)
![check-perpetual-license notification renew](check-perpetual-license.d/notification-02-renew.avif)
![check-perpetual-license notification](check-perpetual-license.d/notification.avif)
Requirements and installation
-----------------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -31,14 +31,13 @@ automatically is supported.
> of view. At the same time it can be source of serve breakage. So test
> versions in lab and read
> [changelog ↗️](https://mikrotik.com/download/changelogs/) and
> [forum ↗️](https://forum.mikrotik.com/c/announcements/5) before deploying
> [forum ↗️](https://forum.mikrotik.com/viewforum.php?f=21) before deploying
> to your production environment! Automatic updates should be handled
> with care!
### Sample notifications
### Sample notification
![check-routeros-update notification found](check-routeros-update.d/notification-01-found.avif)
![check-routeros-update notification neighbor](check-routeros-update.d/notification-02-neighbor.avif)
![check-routeros-update notification](check-routeros-update.d/notification.avif)
Requirements and installation
-----------------------------
@ -88,8 +87,6 @@ Be notified when run from scheduler or run it manually:
If an update is found you can install it right away.
![Terminal](check-routeros-update.d/terminal.avif)
Installing script [packages-update](packages-update.md) gives extra options.
Tips & Tricks

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

Before After
Before After

View file

@ -33,9 +33,6 @@ certificate is checked.
> ⚠️ **Warning**: The script does not limit the size of a list, but keep in
> mind that huge lists can exhaust your device's resources (RAM and CPU),
> and may take a long time to process.
> Even crashes for the complete scripting (and CLI) subsystem are possible.
> This should be logged accordingly with warnings when global functions are
> reloaded from scheduler.
Requirements and installation
-----------------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB

View file

@ -35,10 +35,9 @@ The script works around the limitations, for example it does:
It is intended to be run periodically from scheduler, then collects new
log messages and forwards them via notification.
### Sample notifications
### Sample notification
![log-forward notification info](log-forward.d/notification-01-info.avif)
![log-forward notification warn](log-forward.d/notification-02-warn.avif)
![log-forward notification](log-forward.d/notification.avif)
Requirements and installation
-----------------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -33,7 +33,7 @@ Call the function `$InspectVar` with a variable as parameter:
$InspectVar $ModeButton;
![InspectVar](inspectvar.d/01-inspectvar.avif)
![InspectVar](inspectvar.d/inspectvar.avif)
---
[⬅️ Go back to main README](../../README.md)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -43,7 +43,7 @@ It expects an IP address in CIDR notation as argument.
$IPCalc 192.168.88.1/24;
![IPCalc](ipcalc.d/01-ipcalc.avif)
![IPCalc](ipcalc.d/ipcalc.avif)
### IPCalcReturn
@ -53,7 +53,7 @@ the information in a named array.
:put ([ $IPCalcReturn 192.168.88.1/24 ]->"broadcast");
![IPCalcReturn](ipcalc.d/02-ipcalcreturn.avif)
![IPCalcReturn](ipcalc.d/ipcalcreturn.avif)
---
[⬅️ Go back to main README](../../README.md)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Before After
Before After

View file

@ -49,7 +49,7 @@ your server in device's certificate store.
The example below is for `matrix.org`, which uses a trust chain from *Google
Trust Services*. Run this to import the required certificate:
$CertificateAvailable "GTS Root R4" "fetch";
$CertificateAvailable "GTS Root R4";
Replace the CA certificate name with what ever is needed for your server.
You may want to find the

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View file

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Before After
Before After

Some files were not shown because too many files have changed in this diff Show more