Compare commits

...

31 commits

Author SHA1 Message Date
Christian Hesse
228ac39486 Merge branch 'CommitBrief' into next 2026-01-21 16:03:33 +01:00
Christian Hesse
772f745480 Merge branch 'ExitOnError' into next 2026-01-21 16:03:33 +01:00
Christian Hesse
334ff7162a README: update screenshots 2026-01-21 16:03:33 +01:00
Christian Hesse
20c904eea2 mode-button: use $ExitOnError 2026-01-21 16:03:33 +01:00
Christian Hesse
2a5ece122f global-functions: $ScriptInstallUpdate: drop output on commit...
... now that we have it on loading global functions.
2026-01-21 16:03:33 +01:00
Christian Hesse
7e4463473d mod/ssh-keys-import: use $ExitOnError 2026-01-21 16:03:33 +01:00
Christian Hesse
bde26dc1a5 global-functions: give commit info when laoding 2026-01-21 16:03:33 +01:00
Christian Hesse
496bca336c mod/scriptrunonce: use $ExitOnError 2026-01-21 16:03:33 +01:00
Christian Hesse
44990958ea global-functions: $ScriptInstallUpdate: use $CommitBrief 2026-01-21 16:03:33 +01:00
Christian Hesse
dd4421099f mod/notification-telegram: use $ExitOnError 2026-01-21 16:03:33 +01:00
Christian Hesse
582b0f411e global-functions: $FetchUserAgentStr: user $CommitBrief 2026-01-21 16:03:33 +01:00
Christian Hesse
fe987304ea mod/notification-ntfy: use $ExitOnError 2026-01-21 16:03:33 +01:00
Christian Hesse
06fd89c55c global-functions: $DeviceInfo: use $CommitBrief 2026-01-21 16:03:33 +01:00
Christian Hesse
e21495054b mod/notification-matrix: use $ExitOnError 2026-01-21 16:03:33 +01:00
Christian Hesse
8492e3d7a1 global-functions: introduce $CommitBrief 2026-01-21 16:03:33 +01:00
Christian Hesse
a7217fa0cd mod/notification-gotify: use $ExitOnError 2026-01-21 16:03:33 +01:00
Christian Hesse
b48523cc3d mod/notification-email: use $ExitOnError 2026-01-21 16:03:33 +01:00
Christian Hesse
0393a783c9 mod/ipcalc: use $ExitOnError 2026-01-21 16:03:33 +01:00
Christian Hesse
57d820f454 mod/inspectvar: use $ExitOnError 2026-01-21 16:03:33 +01:00
Christian Hesse
f570b901a8 mod/bridge-port-vlan: use $ExitOnError 2026-01-21 16:03:33 +01:00
Christian Hesse
fe09981801 mod/bridge-port-to: use $ExitOnError 2026-01-21 16:03:33 +01:00
Christian Hesse
2030769216 accesslist-duplicates: use $ExitOnError 2026-01-21 16:03:33 +01:00
Christian Hesse
ce2ae4fdf7 global-functions: $SendNotification: use $ExitOnError 2026-01-21 16:03:33 +01:00
Christian Hesse
14b8768b41 global-functions: $ScriptInstallUpdate: use $ExitOnError 2026-01-21 16:03:33 +01:00
Christian Hesse
f642b2f40d global-functions: make $ExitError a wrapper for $ExitOnError 2026-01-21 16:03:33 +01:00
Christian Hesse
0f9476df28 global-functions: introduce $ExitOnError
This is just like $ExitError, but first parameter is dropped. Soon
we will not need that, now that we can exit a script with :exit.
2026-01-21 16:03:07 +01:00
Christian Hesse
e27aca0664 global-functions: enable scheduler if disabled 2026-01-21 16:00:46 +01:00
Christian Hesse
426da3e99c global-functions: simplify the scheduler fix 2026-01-21 16:00:46 +01:00
Christian Hesse
160a885e02 global-functions: make the scheduler fix a block 2026-01-21 16:00:46 +01:00
Christian Hesse
2d53e81292 global-functions: $NetMask6: drop unused variable 2026-01-21 16:00:46 +01:00
Christian Hesse
f0b1ca8030 README: reword the section on device-mode
Now that we require RouterOS 7.17 *all* devices come with the
updated device-mode.
2026-01-21 16:00:46 +01:00
20 changed files with 75 additions and 59 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Before After
Before After

View file

@ -57,11 +57,12 @@ temporarily.
#### Prerequisite configuration #### Prerequisite configuration
Starting with RouterOS 7.17 the The
[device-mode ↗️](https://help.mikrotik.com/docs/spaces/ROS/pages/93749258/Device-mode) [device-mode ↗️](https://help.mikrotik.com/docs/spaces/ROS/pages/93749258/Device-mode)
has been extended to give more fine-grained control over what features are is a mechanism to lock down a device for security reasons, it gives
available. You need to enable `scheduler` and `fetch` at least, specific fine-grained control over what features are available. You need to enable
scripts may require additional features. `scheduler` and `fetch` at least, specific scripts may require additional
features.
### Hardware ### Hardware

View file

@ -32,5 +32,5 @@
:set ($Seen->$Mac) 1; :set ($Seen->$Mac) 1;
} }
} do={ } do={
:global ExitError; $ExitError false [ :jobname ] $Err; :global ExitOnError; $ExitOnError [ :jobname ] $Err;
} }

View file

@ -32,5 +32,5 @@
:set ($Seen->$Mac) 1; :set ($Seen->$Mac) 1;
} }
} do={ } do={
:global ExitError; $ExitError false [ :jobname ] $Err; :global ExitOnError; $ExitOnError [ :jobname ] $Err;
} }

View file

@ -41,5 +41,5 @@
:set ($Seen->$Mac) 1; :set ($Seen->$Mac) 1;
} }
} do={ } do={
:global ExitError; $ExitError false [ :jobname ] $Err; :global ExitOnError; $ExitOnError [ :jobname ] $Err;
} }

View file

@ -32,5 +32,5 @@
:set ($Seen->$Mac) 1; :set ($Seen->$Mac) 1;
} }
} do={ } do={
:global ExitError; $ExitError false [ :jobname ] $Err; :global ExitOnError; $ExitOnError [ :jobname ] $Err;
} }

View file

@ -30,12 +30,14 @@
:global CharacterReplace; :global CharacterReplace;
:global CleanFilePath; :global CleanFilePath;
:global CleanName; :global CleanName;
:global CommitBrief;
:global DeviceInfo; :global DeviceInfo;
:global Dos2Unix; :global Dos2Unix;
:global DownloadPackage; :global DownloadPackage;
:global EitherOr; :global EitherOr;
:global EscapeForRegEx; :global EscapeForRegEx;
:global ExitError; :global ExitError;
:global ExitOnError;
:global FetchHuge; :global FetchHuge;
:global FetchUserAgentStr; :global FetchUserAgentStr;
:global FileExists; :global FileExists;
@ -319,13 +321,24 @@
:return $Return; :return $Return;
} }
# get readable device info # return a brief commit description
:set DeviceInfo do={ :set CommitBrief do={
:global CommitId; :global CommitId;
:global CommitInfo; :global CommitInfo;
:if ($CommitId = "unknown") do={
:return "unknown";
}
:return ($CommitInfo . "/" . [ :pick $CommitId 0 8 ]);
}
# get readable device info
:set DeviceInfo do={
:global ExpectedConfigVersion; :global ExpectedConfigVersion;
:global Identity; :global Identity;
:global CommitBrief;
:global IfThenElse; :global IfThenElse;
:global FormatLine; :global FormatLine;
@ -366,8 +379,7 @@
$RouterBoard->"current-firmware" != $RouterBoard->"upgrade-firmware") \ $RouterBoard->"current-firmware" != $RouterBoard->"upgrade-firmware") \
([ $FormatLine " Firmware" ($RouterBoard->"current-firmware") ] . "\n") ] . \ ([ $FormatLine " Firmware" ($RouterBoard->"current-firmware") ] . "\n") ] . \
"RouterOS-Scripts:\n" . \ "RouterOS-Scripts:\n" . \
[ $IfThenElse ($CommitId != "unknown") \ [ $FormatLine " Commit" [ $CommitBrief ] ] . "\n" . \
([ $FormatLine " Commit" ($CommitInfo . "/" . [ :pick $CommitId 0 8 ]) ] . "\n") ] . \
[ $FormatLine " Version" $ExpectedConfigVersion ]); [ $FormatLine " Version" $ExpectedConfigVersion ]);
} }
@ -473,20 +485,30 @@
:return $Return; :return $Return;
} }
# simple macro to print error message on unintentional error # wrapper for $ExitOnError with additional parameter
:set ExitError do={ :set ExitError do={
:local ExitOK [ :tostr $1 ]; :local ExitOK [ :tostr $1 ];
:local Name [ :tostr $2 ]; :local Name [ :tostr $2 ];
:local Error [ :tostr $3 ]; :local Error [ :tostr $3 ];
:global ExitOnError;
:if ($ExitOK = "false") do={
$ExitOnError $Name $Error;
}
}
# simple macro to print error message on unintentional error
:set ExitOnError do={
:local Name [ :tostr $1 ];
:local Error [ :tostr $2 ];
:global IfThenElse; :global IfThenElse;
:global LogPrint; :global LogPrint;
:if ($ExitOK = "false") do={ $LogPrint error $Name ([ $IfThenElse ([ :pick $Name 0 1 ] = "\$") \
$LogPrint error $Name ([ $IfThenElse ([ :pick $Name 0 1 ] = "\$") \ "Function" "Script" ] . " '" . $Name . "' exited with error" . \
"Function" "Script" ] . " '" . $Name . "' exited with error" . \ [ $IfThenElse (!($Error ~ "^(|true|false)\$")) (": " . $Error) "." ]);
[ $IfThenElse (!($Error ~ "^(|true|false)\$")) (": " . $Error) "." ]);
}
} }
# fetch huge data to file, read in chunks # fetch huge data to file, read in chunks
@ -550,16 +572,13 @@
:set FetchUserAgentStr do={ :set FetchUserAgentStr do={
:local Caller [ :tostr $1 ]; :local Caller [ :tostr $1 ];
:global CommitId; :global CommitBrief;
:global CommitInfo;
:global IfThenElse; :global IfThenElse;
:local Resource [ /system/resource/get ]; :local Resource [ /system/resource/get ];
:return ("User-Agent: Mikrotik/" . $Resource->"version" . " " . $Resource->"architecture-name" . \ :return ("User-Agent: Mikrotik/" . $Resource->"version" . " " . $Resource->"architecture-name" . \
" " . $Caller . "/Fetch (https://rsc.eworm.de/" . [ $IfThenElse ($CommitId != "unknown") \ " " . $Caller . "/Fetch (https://rsc.eworm.de/; " . [ $CommitBrief ] . ")");
("; " . $CommitInfo . "/" . [ :pick $CommitId 0 8 ]) ] . ")");
} }
# check for existence of file, optionally with type # check for existence of file, optionally with type
@ -1024,7 +1043,6 @@
# return an IPv6 netmask for CIDR # return an IPv6 netmask for CIDR
:set NetMask6 do={ :set NetMask6 do={
:local FuncName $0;
:local CIDR [ :tostr $1 ]; :local CIDR [ :tostr $1 ];
:global IfThenElse; :global IfThenElse;
@ -1241,7 +1259,6 @@
:local NewComment [ :tostr $2 ]; :local NewComment [ :tostr $2 ];
:global CommitId; :global CommitId;
:global CommitInfo;
:global ExpectedConfigVersion; :global ExpectedConfigVersion;
:global GlobalConfigReady; :global GlobalConfigReady;
:global GlobalFunctionsReady; :global GlobalFunctionsReady;
@ -1417,10 +1434,6 @@
} }
} }
:if ($CommitId != "unknown" && $CommitIdBefore != $CommitId) do={
$LogPrint info $0 ("Updated to commit: " . $CommitInfo . "/" . [ :pick $CommitId 0 8 ]);
}
:if ($ExpectedConfigVersionBefore > $ExpectedConfigVersion) do={ :if ($ExpectedConfigVersionBefore > $ExpectedConfigVersion) do={
$LogPrint warning $0 ("The configuration version decreased from " . \ $LogPrint warning $0 ("The configuration version decreased from " . \
$ExpectedConfigVersionBefore . " to " . $ExpectedConfigVersion . \ $ExpectedConfigVersionBefore . " to " . $ExpectedConfigVersion . \
@ -1517,7 +1530,7 @@
:set GlobalConfigMigration; :set GlobalConfigMigration;
} }
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }
# lock script against multiple invocation # lock script against multiple invocation
@ -1663,7 +1676,7 @@
$SendNotification2 ({ origin=$0; subject=$1; message=$2; link=$3; silent=$4 }); $SendNotification2 ({ origin=$0; subject=$1; message=$2; link=$3; silent=$4 });
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }
# send notification via NotificationFunctions - expects one array argument # send notification via NotificationFunctions - expects one array argument
@ -1921,18 +1934,20 @@
} }
# add (and fix) global scripts scheduler # add (and fix) global scripts scheduler
:local OnEvent "/system/script { run global-config; run global-functions; }"; /system/scheduler {
:if ([ :len [ /system/scheduler/find where name="global-scripts" ] ] = 0) do={ :local OnEvent "/system/script { run global-config; run global-functions; }";
/system/scheduler/add name="global-scripts" start-time=startup; :if ([ :len [ find where name="global-scripts" ] ] = 0) do={
} add name="global-scripts" start-time=startup;
:if ([ /system/scheduler/get "global-scripts" on-event ] != $OnEvent) do={ }
/system/scheduler/set "global-scripts" on-event=$OnEvent; set on-event=$OnEvent [ find where name="global-scripts" on-event!=$OnEvent ];
enable [ find where name="global-scripts" disabled ];
} }
# Log success # Log success
:local Resource [ /system/resource/get ]; :local Resource [ /system/resource/get ];
$LogPrintOnce info $ScriptName ("Loaded on " . $Resource->"board-name" . \ $LogPrintOnce info $ScriptName ("Loaded " . \
" with RouterOS " . $Resource->"version" . "."); [ $IfThenElse ($CommitId != "unknown") ([ $CommitBrief ] . " ") ] . \
"on " . $Resource->"board-name" . " with RouterOS " . $Resource->"version" . ".");
# signal we are ready # signal we are ready
:set GlobalFunctionsReady true; :set GlobalFunctionsReady true;

View file

@ -66,5 +66,5 @@
/interface/ethernet/enable $InterfaceReEnable; /interface/ethernet/enable $InterfaceReEnable;
} }
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }

View file

@ -75,5 +75,5 @@
/interface/ethernet/enable $InterfaceReEnable; /interface/ethernet/enable $InterfaceReEnable;
} }
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }

View file

@ -17,7 +17,7 @@
:put [ :tocrlf [ $InspectVarReturn $1 ] ]; :put [ :tocrlf [ $InspectVarReturn $1 ] ];
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }
# inspect variable and return formatted string # inspect variable and return formatted string

View file

@ -28,7 +28,7 @@
[ $FormatLine "HostMax" ($Values->"hostmax") ] . "\n" . \ [ $FormatLine "HostMax" ($Values->"hostmax") ] . "\n" . \
[ $FormatLine "Broadcast" ($Values->"broadcast") ]) ]; [ $FormatLine "Broadcast" ($Values->"broadcast") ]) ];
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }
# calculate and return netmask, network, min host, max host and broadcast # calculate and return netmask, network, min host, max host and broadcast

View file

@ -146,7 +146,7 @@
/system/scheduler/set interval=(($SchedVal->"run-count") . "m") \ /system/scheduler/set interval=(($SchedVal->"run-count") . "m") \
comment="Waiting for retry..." $Scheduler; comment="Waiting for retry..." $Scheduler;
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }
# generate filter for log-forward # generate filter for log-forward
@ -274,7 +274,7 @@
$SendEMail2 ({ origin=$0; subject=$1; message=$2; link=$3 }); $SendEMail2 ({ origin=$0; subject=$1; message=$2; link=$3 });
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }
# send notification via e-mail - expects one array argument # send notification via e-mail - expects one array argument

View file

@ -54,7 +54,7 @@
:set GotifyQueue; :set GotifyQueue;
} }
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }
# send notification via Gotify - expects one array argument # send notification via Gotify - expects one array argument
@ -126,7 +126,7 @@
$SendGotify2 ({ origin=$0; subject=$1; message=$2; link=$3; silent=$4 }); $SendGotify2 ({ origin=$0; subject=$1; message=$2; link=$3; silent=$4 });
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }
# send notification via Gotify - expects one array argument # send notification via Gotify - expects one array argument

View file

@ -59,7 +59,7 @@
:set MatrixQueue; :set MatrixQueue;
} }
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }
# send notification via Matrix - expects one array argument # send notification via Matrix - expects one array argument
@ -172,7 +172,7 @@
$SendMatrix2 ({ origin=$0; subject=$1; message=$2; link=$3 }); $SendMatrix2 ({ origin=$0; subject=$1; message=$2; link=$3 });
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }
# send notification via Matrix - expects one array argument # send notification via Matrix - expects one array argument

View file

@ -53,7 +53,7 @@
:set NtfyQueue; :set NtfyQueue;
} }
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }
# send notification via ntfy - expects one array argument # send notification via ntfy - expects one array argument
@ -148,7 +148,7 @@
$SendNtfy2 ({ origin=$0; subject=$1; message=$2; link=$3; silent=$4 }); $SendNtfy2 ({ origin=$0; subject=$1; message=$2; link=$3; silent=$4 });
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }
# send notification via ntfy - expects one array argument # send notification via ntfy - expects one array argument

View file

@ -62,7 +62,7 @@
:set TelegramQueue; :set TelegramQueue;
} }
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }
# get the chat id # get the chat id
@ -101,7 +101,7 @@
$LogPrint info $0 ("The thread id is: " . ($Message->"message_thread_id")); $LogPrint info $0 ("The thread id is: " . ($Message->"message_thread_id"));
} }
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }
# send notification via telegram - expects one array argument # send notification via telegram - expects one array argument
@ -237,7 +237,7 @@
$SendTelegram2 ({ origin=$0; subject=$1; message=$2; link=$3; silent=$4 }); $SendTelegram2 ({ origin=$0; subject=$1; message=$2; link=$3; silent=$4 });
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }
# send notification via telegram - expects one array argument # send notification via telegram - expects one array argument

View file

@ -52,5 +52,5 @@
:return true; :return true;
} }
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }

View file

@ -68,7 +68,7 @@
:return false; :return false;
} }
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }
# import keys from a file # import keys from a file
@ -110,5 +110,5 @@
} }
} }
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }

View file

@ -82,7 +82,7 @@
$LogPrint info $FuncName ("No action defined for " . $Count . " mode-button presses."); $LogPrint info $FuncName ("No action defined for " . $Count . " mode-button presses.");
} }
} do={ } do={
:global ExitError; $ExitError false $0 $Err; :global ExitOnError; $ExitOnError $0 $Err;
} } } }
/system/scheduler/add name="_ModeButtonScheduler" \ /system/scheduler/add name="_ModeButtonScheduler" \
on-event=":global ModeButtonScheduler; \$ModeButtonScheduler;" interval=3s; on-event=":global ModeButtonScheduler; \$ModeButtonScheduler;" interval=3s;
@ -91,5 +91,5 @@
/system/scheduler/set $Scheduler start-time=[ /system/clock/get time ]; /system/scheduler/set $Scheduler start-time=[ /system/clock/get time ];
} }
} do={ } do={
:global ExitError; $ExitError false [ :jobname ] $Err; :global ExitOnError; $ExitOnError [ :jobname ] $Err;
} }