Community discussions

 
tjc
Member Candidate
Member Candidate
Topic Author
Posts: 279
Joined: Sun Jul 10, 2011 3:08 am

Handling expected errors?

Wed Aug 31, 2011 8:09 am

So I got curious about where the trouble makers in my blacklist were coming from and tried something like this:
/ip firewall address-list> :foreach a in=[find where list=blacklist dynamic] do={:put [:resolve [/ip firewall address-list get $a address]] }
It's supposed to walk through the dynamic addresses in my blacklist and if it can resolve them to a host name, print it. Sadly it bombed on the first address which wouldn't resolve.

Now maybe I'm missing something, but I couldn't figure out how to get a script to ignore an expected error and march on like a good soldier. This is a pretty normal thing to do in a script after all, since you're often trying to determine exactly that, which of these are valid, or set, or can be found, or ...

Can someone provide a clue?
 
User avatar
janisk
MikroTik Support
MikroTik Support
Posts: 6283
Joined: Tue Feb 14, 2006 9:46 am
Location: Riga, Latvia

Re: Handling expected errors?

Wed Aug 31, 2011 9:56 am

script will stop on first error.

So you have to have 2 scripts, one that runs and does stuff and handles situation when some value is not received as expected, and other script does the job, that can fail. as a result, if second script fails, first one that called second script to do the job will continue.
 
tjc
Member Candidate
Member Candidate
Topic Author
Posts: 279
Joined: Sun Jul 10, 2011 3:08 am

Re: Handling expected errors?

Thu Sep 01, 2011 5:35 am

OK, that gives me some ideas, but it seems really... clunky.

Two scripts to do a simple loop, just because one command could fail, seems to cry out for a bit of language support, like a ":try" or something, or maybe a flavor of [] command substitution that deals with errors.
 
psamsig
Member Candidate
Member Candidate
Posts: 161
Joined: Sun Dec 06, 2009 1:36 pm
Location: Denmark

Re: Handling expected errors?

Sat Sep 03, 2011 12:03 pm

It is really silly to have it break a script, and if that wasn't enough, these breaks leads to memory leaks. So it is quite absurd that this hasn't been dealt with yet, I resently found a post here on the forum that some kind of try/catch was being cosidered, but that was two years ago, so I wouldn't hold your breath.
If it is because MikroTik is afraid of breaking excisting scripts (not a concern they usually have), I have two simple ways it could be done, add either a parameter (e.g. break-on-fail=no) that indicates whether or not you want it to break on fail or just return :type 'nothing', this is after all the behavior most would have expected in the first place, secondly a paramerter (e.g. address-on-fail=0.0.0.0), which would return a dummy address of your choice on fail.

Until a scripting solution comes along, there is other alternatives, use a DNS server with a default responce like OpenDNS, they return one of two adresses to unresolvable domains, it may not be pretty, but it works, and since you know (since ROS 5.0beta-something) can tell :resolve which DNS server to use, you don't have to change your whole DNS infrastructure to OpenDNS.
Last edited by psamsig on Sat Sep 03, 2011 8:45 pm, edited 1 time in total.
 
tjc
Member Candidate
Member Candidate
Topic Author
Posts: 279
Joined: Sun Jul 10, 2011 3:08 am

Re: Handling expected errors?

Sat Sep 03, 2011 7:27 pm

Since the scripting language doesn't even seem to provide a way to pass parameters to scripts without using global variables (I'd be delighted to learn otherwise) it's especially annoying. To put the resolve into a "safe" wrapper you need to set a global for the input parameter, set another global for the output value, ...

Given that the language already has scopes, parameters are just a tiny step.
 
tjc
Member Candidate
Member Candidate
Topic Author
Posts: 279
Joined: Sun Jul 10, 2011 3:08 am

Re: Handling expected errors?

Sun Sep 04, 2011 1:37 am

Wow... When you isolate the problem command in it's own script and run it. It still breaks the outer script. That's just plain broken.

janisk - What am I doing wrong here? AFAICT this is what you told me works.
 1   name="safe-resolve" owner="admin" policy=read,write,test last-started=sep/03/2011 18:29:22 run-count=99 source=
       :global inAddr;
       :global outAddr "";

       :set outAddr [:resolve $inAddr];

 2   name="blacklist-names" owner="admin" policy=read,write,test last-started=sep/03/2011 18:29:20 run-count=12 source=
       :global inAddr;
       :global outAddr;
       
       :foreach addr in=[/ip firewall address-list find where list=blacklist dynamic] do={
           set inAddr [/ip firewall address-list get $addr address];
           /system script run safe-resolve;
           :if ($outAddr != "") do={
               :put $outAddr;
           }
       }
[admin@MikroTik] /system script> run blacklist-names;
pool-109-191-246-40.is74.ru
87-126-71-139.btc-net.bg
57.88.178.61.dail.lz.gs.dynamic.163data.com.cn
dynamicip-46-0-145-205.pppoe.samara.ertelecom.ru
mx-ll-180.183.141-17.dynamic.3bb.co.th
ip136.hichina.com
failure: dns name does not exist
 
SurferTim
Forum Guru
Forum Guru
Posts: 4637
Joined: Mon Jan 07, 2008 10:31 pm
Location: Miramar Beach, Florida

Re: Handling expected errors?

Tue Sep 06, 2011 1:49 pm

Last I checked, scripts run concurrently. They do not run like a function. When you execute a script from another script, the calling script does not wait for the called script to finish, but continues to run.

I would use this. I added the global variable "done" to both scripts. The calling script sets done to false, executes the other script, then waits for the called script to set done true before continuing.
1   name="safe-resolve" owner="admin" policy=read,write,test last-started=sep/03/2011 18:29:22 run-count=99 source=
       :global done
       :global inAddr
       :global outAddr ""

       :set outAddr [:resolve $inAddr]
       :set done true

2   name="blacklist-names" owner="admin" policy=read,write,test last-started=sep/03/2011 18:29:20 run-count=12 source=
       :global done
       :global inAddr
       :global outAddr
       
       :foreach addr in=[/ip firewall address-list find where list=blacklist dynamic] do={
           :set inAddr [/ip firewall address-list get $addr address]

           :set done false
           :execute safe-resolve
           :while(!$done) do={:nothing}

           :if ($outAddr != "") do={
               :put $outAddr
           }
       }
You might want to put a count on the while(!done) loop to terminate it if the called script fails to set done true after several times through the loop.
 
tjc
Member Candidate
Member Candidate
Topic Author
Posts: 279
Joined: Sun Jul 10, 2011 3:08 am

Re: Handling expected errors?

Wed Sep 07, 2011 6:51 am

":execute script-name" - not documented in the manual on the wiki, but does seems to run the script in the background.
"/system script run script-name" - doesn't seem to do that.

That just leaves the problem of synchronization... And why :resolve often returns nothing when nslookup (using the router as it's DNS) gets a result...

Thanks for the clues...
 
User avatar
janisk
MikroTik Support
MikroTik Support
Posts: 6283
Joined: Tue Feb 14, 2006 9:46 am
Location: Riga, Latvia

Re: Handling expected errors?

Wed Sep 07, 2011 10:53 am

there was some work done on :resolve it returns IPv4 address (A record) if that is not available, IPv6 (AAAA records) or fail.

what ROS version you are using?
 
SurferTim
Forum Guru
Forum Guru
Posts: 4637
Joined: Mon Jan 07, 2008 10:31 pm
Location: Miramar Beach, Florida

Re: Handling expected errors?

Wed Sep 07, 2011 3:12 pm

I am aware that the ":execute" command is not documented, but it should be. It works really well. I've been using it since the V2.9.x era.

The synchronization is handled by the "done" variable. That is the "while not done, do nothing" loop. But you will need to add a loop count to that to break from the loop after a dozen or so iterations. Should be something like this:
:local loopCount
:local loopError

:set done false
:execute myScript
:set loopCount 0
:set loopError false
:while(!$done) do={

   :set loopCount $loopCount + 1

   if($loopCount > 11) do={
      :set done true
      :set loopError true   
   }
}
I have not checked this for errors.

By my tests, the scripts are run one command/loop iteration at a time in each running script. So it works like this:
execute command 1 in script 1
execute command 1 in script 2
execute command 2 in script 1
execute command 2 in script 2
...and on.
 
tjc
Member Candidate
Member Candidate
Topic Author
Posts: 279
Joined: Sun Jul 10, 2011 3:08 am

Re: Handling expected errors?

Thu Sep 08, 2011 6:54 am

what ROS version you are using?
Running RouterOS 5.6.

On the other hand I was just testing with
:put [:resolve <ip-address-here>]
and did not see any problems. I may have just been at the point where the code on the screen all turns to meaningless squiggly lines, and forgot the ":print" part.
 
tjc
Member Candidate
Member Candidate
Topic Author
Posts: 279
Joined: Sun Jul 10, 2011 3:08 am

Re: Handling expected errors?

Thu Sep 08, 2011 7:25 am

I am aware that the ":execute" command is not documented, but it should be. It works really well. I've been using it since the V2.9.x era.
Yeah, mostly just grumbling about the gaps in the documentation, which can be very frustrating.
The synchronization is handled by the "done" variable. That is the "while not done, do nothing" loop. But you will need to add a loop count to that to break from the loop after a dozen or so iterations.
Yeah, understood that, it was how to limit the loop and whether to use ":delay" or just ":nothing". (Which BTW, is also missing from the scripting docs...) The original loop would have waited forever when a lookup failure occurred.

The scripting language could really stand to have a better synchronization/sequencing mechanism too...

BTW - Miramar Beach in the Destin/FWB area of the redneck riviera? I used to spend way too much time down there on business. Just the names give me flashbacks to driving along 98 when somebody brought an 111 in off the water at full throttle and tree top level, stopping traffic in both directions and leaving the rental car swaying back and forth from the shock wave. It was like a scene from "Close Encounters". ;-)
 
SurferTim
Forum Guru
Forum Guru
Posts: 4637
Joined: Mon Jan 07, 2008 10:31 pm
Location: Miramar Beach, Florida

Re: Handling expected errors?

Thu Sep 08, 2011 1:45 pm

I would prefer the error handling do more than just abort the script if a command fails, but I don't have a solution on how to do that. That part is up to Mikrotik.

It would be handy to "call" scripts (stop execution on main script until child script is complete) rather than just execute them. But there would need to be better error handling or it would fail also when the child script aborts.
Add: Unless the child script returns to the parent script on abort and started executing commands there again. I would be ok with that. :D
Like this
:global done

:set done false
:call myScript
:if(!$done) do={
// now you know it did not finish, but aborted.
// so do what you do on a fail
}
This would be myScript
:global done

// do the stuff that might abort here
// If it aborts, that is the same as "return false"
// then last thing (equivalent of "return true")
:set done true
And I agree that the wiki docs could use some updating.

Thanks for karma.

Yes, this is the "Redneck Riviera". It is not as redneck as it was when I got here in 1986, but I know what you mean.

The military still flies around here, but since the area is no longer considered "sparsely inhabited", the jets can't fly that low here now. I was assigned to Fort Rucker in 1969, and flew Hueys and Chinooks up and down this beach. There was nothing here then.

Military aircraft are not the only low fliers here. Check this out:
http://www.thedestinlog.com/sections/ar ... =0&id=5297
This airplane is stuck into the side of the building about 30' below my backhaul router on the roof.
 
el berto
Member Candidate
Member Candidate
Posts: 197
Joined: Wed Sep 26, 2007 10:53 am

Re: Handling expected errors?

Fri Jun 07, 2013 1:43 pm

Not working (or it's me to make something wrong):


catch_script
:global return
:set return false
:global num

:put ("   try to resolve #".$num)
/resolve [/ip firewall address-list get $num comment]
:set return true
main script
:global num
:local i
:local x 2
:for i from=0 to=$x step 1 do={
   :set num $i
   :put ("checking ".$num)
   /sys script run [find name="catch_script"];
   :if ($return) do={
       :put ($num."= risolto");
   } else={
       :put ($num."= non risolto");
   }
} 

Result:
checking 0
   try to resolve #0
0= risolto
checking 1
   try to resolve #1
1= risolto
checking 2
   try to resolve #2
failure: dns name does not exist
[admin@Morm1] /system script> 


 
psamsig
Member Candidate
Member Candidate
Posts: 161
Joined: Sun Dec 06, 2009 1:36 pm
Location: Denmark

Re: Handling expected errors?

Fri Jun 07, 2013 2:41 pm

With fewer exemptions worth mentioning, never ever assume any entry numbers, they are more often than not, non-sequential.
 
midenok
newbie
Posts: 39
Joined: Fri Dec 27, 2013 5:34 pm

Re: Handling expected errors?

Sat Aug 08, 2015 9:37 am

With v6.2 the state of things have been changed! Look in Scripting Manual for Catch run-time errors:
:do {
      :put [:resolve www.example.com];
} on-error={ :put "resolver failed"};
:put "lala" 

output:

resolver failed
lala
RouterOS 6.34

Who is online

Users browsing this forum: No registered users and 12 guests