Scripting in routeros is not optimized in some important cases. When error occurs, script just stops without logging when and why and further commands were not executed. Most noticed that. If script has error when flashing with netinstall, happens that entire script fails to load. These errors mostly appears because of routeros version changes. I.e. wireless restrictions, bridges. Even upgrading older routers, they can’t execute default script after reset. I have no idea how to upgrade routers and make them work after reset, if script tries to execute commands, that newer routeros do not understand. I guess there are no ways to solve that yet. I think there should be option to ignore only specific error and execute current line without bad command (i.e. interface wireless dfs-mode= was removed in routeros, but was used in script).
Another example I can’t solve: I want to make one script for several models. One has poe-out, other don’t. And I need to disable poe if it exists. So command:
/interface ethernet set [ find default-name=ether5 ] poe-out=off
can be executed if ether5 has poe-out, but if it don’t, poe-out can’t exist in command line. Are there any ways to make command work on both models?
You can even test if an interface has poe like this and only run command when interface has poe
:local test [/interface ethernet get ether5]
:if ($test~"poe-out") do={
:put "yes has poe"
/interface ethernet set [ find default-name=ether5 ] poe-out=off
} else={
:put "does not have poe"
}
But it does not help since script gives fail on poe-out=off if you do not have poe on your board.
To test or write poe-out in condition part is not the problem. Problem is to make routeros think, that executable line is not wrong if it is not executed. Maybe it is possible to make “poe-out=off” as string and put it in line then needed?
It is a syntax error if parameter does not exist, and you cannot catch these errors at runtime.
One way is to use “parse” command to execute command line based on parameters, which check if poe should exist on this router.
As I imagine it is not an option if I want to flash script with netinstall, is it? As I mentioned, is it possible to use i.e. str1=“poe-out=off” as variable and use in command line then needed, or otherwise set str1=“” or str1=null or something?
Any ideas why this part is not working when I flash with netinstall? I put this code in {}, for local variables to work, but still nothing. It works as script in routeros, but not as a part of booting script, flashed with netinstall.
My code starts from waiting interfaces to appear and then executes the rest. I replaced line /interface ethernet set [ find default-name=ether5 ] poe-out=off with this code. So it is not the case. There is something else in code that fails when booting.
I am learning from this as well, see there are other ways to do things
So to clean your code some.
You do not need ; at the end of each line, only when there are multiple commands on same line, use ; to separate it.
Also no need to use variables, use the code directly.
Use tab in if/loop etc to make it more readable.
This should works fine:
{
:if ([/interface ethernet get ether5]~"poe-out") do={
[:parse "/interface ethernet set [find default-name=ether5] poe-out=off"]
:log info "Ether5 POE disabled"
} else= {
:log info "No POE on Ether5"
}
}
This did make me update my MikroTik for Splunk script to handle when routers does not have temperature, so changed from:
:local voltage ([/system health get voltage]/10)
:local temperature ([/system health get temperature])
:log info message="script=health voltage=$voltage V temperature=$temperature C"
to:
:if ([/system health get]~"temperature") do={
:local voltage ([/system health get voltage]/10)
:local temperature ([/system health get temperature])
:log info message="script=health voltage=$voltage V temperature=$temperature C"
}
Even if both did work, its more cleaner to not get error message in the script. (see link my signature for more info)
Apologies for the necro-post but this seemed the most appropriate place to post my similar issue.
I have a default router config script that I’ve written to work on as many Routerboards as possible (currently tested on RB931, RB951, RB952, RB9600, hAP AC 3.. probably a few others).
I’ve kept it up-to-date with the [many and varied] syntax changes we’ve seen over the years but I’m having issues now we’re deploying hAP ax2 and adding wave2 support for hAP AC 3
I’ve worked-around it so far with :parse but I’ve one command left I can’t get to work -
:foreach i in=[/interface wireless find] do={
:local LAN [/interface wireless get $i name]
/interface bridge port add bridge=bridge interface=$LAN
I have tried stripping it down quite a bit in tests, but at the end of the day it’s still a function inside a function, which parse can’t really deal with? -
:if ([:len [/system package find name~"wave2"]]=0 or [system package get [find name~"wave2"] disabled]=true) do={
[:parse ":do {:foreach i in=[/interface wireless find] do={:local LAN [/interface wireless get $i name];/interface bridge port add bridge=bridge interface=$LAN}}"];
}
I don’t have a way to test, but I think you use need to escape the the $LAN and $I in the :parse – otherwise string interpolation is going to kick in before the parse happens. Since $LAN and $I don’t exist before the parse, there replaced as empty string, so when the parse happens it becomes an invalid command
:if ([:len [/system package find name~"wave2"]]=0 or [system package get [find name~"wave2"] disabled]=true) do={
[:parse ":do {:foreach i in=[/interface wireless find] do={:local LAN [/interface wireless get \$i name];/interface bridge port add bridge=bridge interface=\$LAN}}"];
}
The correct way to know if is present one (or more) wireless interface is count the result of [/int find where type=“wlan”]
This work also if the wifiwave2 package is installed and/or the standard “wireless” packaged disabled or supreseeded by the wifiwave2 package
Summarizing:
:put [/interface find where type="wlan"]
# print the number of wifi interfaces on both v6 and v7, but not if the wifiwave2 is installed (on v7 do not do any error)
:put [/interface find where type="wifi"]
# print the number of wifiwave2 interfaces only on v7, but not the standard wlan interfaces, work both on v6 and v7: on v6 do not do any error