Page 1 of 1
How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 6:47 pm
by mutluit
How to auto-start a user script at interface link up, and auto-start another user script at interface link down?
Is this possible in RouterOS? If not, then any alternative solution possible, ie. a workaround?
I'm seeking a solution for CRS switch devices with RouterOS in Bridge Mode (I think the procedure could be the same on router devices).
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 7:45 pm
by pe1chl
It is not possible in the generic case. In some special cases it is, e.g. for a PPP-type interface.
The workaround is to make a script that is scheduled at some interval, and keep the previous status in a global variable.
You script compares the current status with the previous status in the global variable, acts accordingly, and finally copies the current status to the variable before it exits.
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 8:11 pm
by mutluit
It is not possible in the generic case. In some special cases it is, e.g. for a PPP-type interface.
The workaround is to make a script that is scheduled at some interval, and keep the previous status in a global variable.
You script compares the current status with the previous status in the global variable, acts accordingly, and finally copies the current status to the variable before it exits.
Too bad. I think MT should implement such a functionality. After all it's already present in the underlying Linux OS,
MT should just write a wrapper on top of it for ROS.
Ok, whatever, I'll try to solve my problem with the said workaround using the scheduler. Lucky me it's not that a time-critical task.
Thank you.
Update:
Already encountered my first problem with this approach: how can I check whether a global variable already exists? (forgive me, I'm a newbie in ROS
)
Because it of course wouldn't be correct if the variable gets initialized in each time interval when the script gets fired...
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 8:17 pm
by mbovenka
I'm seeking a solution for CRS switch devices with RouterOS in Bridge Mode (I think the procedure could be the same on router devices).
Well, if it had been a router interface, you could have set up a netwatch for the interface IP address. But I agree, a generic script trigger on interface state change would be useful.
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 10:08 pm
by mutluit
Why is it not possible to output $gArr in this code (in the ":put $gArr" line) ? :
{
:local f [:tobool [:len $gArr]]
:if ($f = false) do={
:global gArr [:toarray ""]
:set ($gArr->"key1") "val1"
}
:put $gArr
}
gArr gets filled, but it does not output it in this script. Why not?
OTOH doing the same ":put $gArr" in the shell prompt does it right. That's really weirdo, man!
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 10:12 pm
by msatter
You can print in /system script environment.
If :global is not found set it with a value:
$shortname contains the variable name used in environment.
:if ([/system script environment find name=$shortName]) do={} else={[:parse "global $shortName 99"];};
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 10:16 pm
by mutluit
You can print in /system script environment.
This is a script installed under /system/script under a name "test".
Executing it from inside /system/script with this command:
run test
It executes it, but the said line in the script does not print anything.
Or do you mean something else I maybe have overlooked?
@msatter, I need to do it inside the script, not myself manually in the terminal. Is that not possible?
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 10:17 pm
by msatter
I gave two answers to two questions.
In environment all globals live. If not there then it is not a global.
Why do you need print while you have put and set?
For your script it is known that tobool is broken since a long time.
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 10:22 pm
by mutluit
I gave two answers to two questions.
In environment all globals live. If not there then it is not a global.
Why do you need print while you have put and set?
Man, by print I really mean this ":put" function or command or how else it is called.
Why not? I'm just playing around & trying to learn this funny language.
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 10:25 pm
by msatter
The print is a official command like put is. Print can do other stuff then put and they are used to their specific purpose.
Print is print and put is printing using put. Some things are just not straight forward.
The variable is returned as a string and tobool will not convert it. You could just compare to the word true or false. Otherwise you first have to set again depending on the string value.
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 10:27 pm
by mutluit
For your script it is known that tobool is broken since a long time.
Is this documented somewhere?
I did not see any such warning in the official scripting web page documentation where I had found it.
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 10:28 pm
by mutluit
The print is a official command like put is. Print can do other stuff then put and they are used to their specific purpose.
Print is print and put is printing using put. Some things are just not straight forward.
In the said script ":put" is used, I just said "printing". But it's clear from the context what is meant.
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 10:33 pm
by msatter
Most of the time but as soon you enter /system script environment and want see the values then you use print. It is a mix and one part of you line you are in printing area and to print the variable outside that, put is used.
If you can't print by using put try print, is one thing to remind.
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 10:36 pm
by mutluit
Can please anybody else take a look at my code in #5 ? Thx.
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 10:37 pm
by msatter
What's new in 6.46beta44 (2019-Sep-19 05:54):
Changes in this release:
*) capsman - fixed channel auto reselection;
*) chr - added support for Azure guest agent;
*) console - fixed "tobool" conversion;
As you noticed, it is not.
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 10:40 pm
by mutluit
What's new in 6.46beta44 (2019-Sep-19 05:54):
Changes in this release:
*) capsman - fixed channel auto reselection;
*) chr - added support for Azure guest agent;
*) console - fixed "tobool" conversion;
As you noticed, it is not.
It is not what? Not fixed?
Come on, that is the changelog of last year, and it clearly says that it is fixed. And I'm using the 7.0beta5 from 2020.
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 10:42 pm
by msatter
You are barking up the wrong tree here.
I had this exact same problem a few weeks ago and I worked around it going with returned string value.
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 10:53 pm
by mutluit
I would say there is an error in the script parser regarding "visibility" of scope levels...
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 11:03 pm
by msatter
I am not a programmer but this is my solution:
{
:set $f [:len $gArr]
:if ($f = "true") do={:set $f true} else={:set $f false};
:if ($f) do={} else={
:global gArr [:toarray ""]
:set ($gArr->"key1") "val1"
}
:put [:pick $gArr 0]
}
Nothing is being printed but the value is there "key1=val1".
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 11:09 pm
by eworm
You initialize the variable inside a block, thus it's not visible outside.
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 11:12 pm
by mutluit
You initialize the variable inside a block, thus it's not visible outside.
But it's a global variable
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 11:12 pm
by msatter
It is a global variable:
{
{... :set $f [:len $gArr]
{... :if ($f = "true") do={:set $f true} else={:set $f false};
{... :if ($f) do={} else={
{{... :global gArr [:toarray ""]
{{... :set ($gArr->"key1") "val1"
{{... }
{...
{... :put [:pick $gArr 0]
{...
{... }
val1
And via de CLI:
:put [:pick $gArr 0]
val1
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 11:17 pm
by mutluit
@msatter, stop please. Your code can't be correct as you use $f in the initialization...
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 11:22 pm
by mutluit
I now asked the MT developers to take a look at #5:
viewtopic.php?f=1&t=161299
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 11:27 pm
by msatter
@msatter, stop please. Your code can't be correct as you use $f in the initialization...
My code is correct, as it runs in RouterOS. $f is local . You don't have always to go through the process of defining it. It not Cobol.
This is a working and also the shortest version:
{
:if ([/system script environment find name="gArr"]) do={} else={:global gArr [:toarray ""]; :set ($gArr->"key1") "val2";};
}
{
:put [pick $gArr]
}
Correction, it is possible to make it even shorter and condense it to only one line:
:if ([/system script environment find name="gArr"]) do={:put $gArr;} else={:global gArr [:toarray ""]; :set ($gArr->"key1") "val2";};
:if ([/system script environment find name="gArr"]) do={:put $gArr;} else={:global gArr [:toarray ""]; :set ($gArr->"key1") "val2";};
key1=val2
On the first run the global variable gArr is created because it does not yet exits and filled with a value. On a second run only the value of the variable gArr is printed by using :put.
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 11:35 pm
by mutluit
@msatter, stop please. Your code can't be correct as you use $f in the initialization...
My code is correct, as it runs in RouterOS. $f is local . You don't have always to go through the process of defining it. It not Cobol.
You are not initializing it, you just change the value of an already existing variable.
Delete the variable ( :set f ) and try again, then you will see...
Re: How to auto-start a script at interface link up / down ?
Posted: Sun May 17, 2020 11:37 pm
by msatter
As soon the interpreter is hitting the "}", $f is forgotten.
But then I have already put up a version that does not need a helping variable.
Re: How to auto-start a script at interface link up / down ?
Posted: Mon May 18, 2020 12:01 am
by eworm
You initialize the variable inside a block, thus it's not visible outside.
But it's a global variable
Sure, it is. But even global variables are accessible only...
- ... when used directly from command line (without block!) or...
- ... when initialized properly.
So when ever you want to access $gArr from a script or block, you have to initialized it with:
Try it:
{
:global gArr;
:if ([ :len $gArr ] = 0) do={
:set gArr [:toarray ""];
:set ($gArr->"key1") "val1";
}
:put $gArr;
}
Re: How to auto-start a script at interface link up / down ?
Posted: Mon May 18, 2020 1:57 am
by msatter
Thanks eworm for the explanation and I have added the :global gArr; line and this can be used directly in a script:
:if ([/system script environment find name="gArr"]) do={} else={:global gArr [:toarray ""]; :set ($gArr->"key1") "val2";};
:global gArr;
:put $gArr;
On a first run it will create the variable gArr and set a value to it which is directly accessible.
On a second or more runs it will only make the global variable accessible because the global variable exits. It allows that the value is changed, and that the last value remains the same until it is changed again or removed.
I thought to put the
:global gArr; in the do={} of of the if..do..else but then it is only accessible inside the if..do..else.
This still looks very strange but it works:
{
if ([/system script environment find name="gArr"]) do={} else={global gArr [toarray ""]; set ($gArr->"key1") "val2"}
global gArr
put $gArr
}
Re: How to auto-start a script at interface link up / down ? [SOLVED]
Posted: Mon May 18, 2020 11:26 am
by mutluit
An elegant solution has been presented by @mrz from MT support:
viewtopic.php?f=1&t=161299&p=794253#p794253
Re: How to auto-start a script at interface link up / down ?
Posted: Mon May 18, 2020 11:31 am
by msatter
O, please stop.
Re: How to auto-start a script at interface link up / down ?
Posted: Tue Oct 12, 2021 1:41 pm
by trutec
I would suggest you to look into
system / logging - create a new rule for topic interface - filter the results and you can also use the remote action