Community discussions

MikroTik App
 
MakroTok
newbie
Topic Author
Posts: 28
Joined: Wed Dec 04, 2019 4:36 pm

Retrieveing a global variable readonly to a local variable

Sun Mar 03, 2024 11:39 pm

Is there a more elegant solution to retrieve the value of a global variable without defining one?
:local name "foo";
:local value [/system/script/environment/get [/system/script/environment/find name="$name"] value];
This is a just minimal example but instead of the fixed value "foo" it could also be something dynamic such as [:jobname].
At the moment I'm just experimenting a bit with with what's possible. The basic idea is that the same script could be used multiple times but with different names and by usin :jobname each could have its own configuration without changing the script.
The second idea is that without defining a global varible it cannot be changed. (The downside is that this script needs more permissions than just defining a global variable...)

(It's not needed for anything, I just want to learn about what's possible with scripting.)
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12014
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Retrieveing a global variable readonly to a local variable

Mon Mar 04, 2024 2:08 pm

Unclear.
 
MakroTok
newbie
Topic Author
Posts: 28
Joined: Wed Dec 04, 2019 4:36 pm

Re: Retrieveing a global variable readonly to a local variable

Mon Mar 04, 2024 4:18 pm

  • For a global variable with the "fixed" name "foo" one could just do:
    :global foo;
    
  • For a global variable where the name is "dynamic", eg. because it is e.g. derieved from :jobname one could write
    :global variablename [:jobname];
    :global value;
    [:parse "global $variablename;:global value \$$variablename"]
    
All these require at least one or more globals to be defined.

The basic idea/question is if one is able to treat the globals as constants in anyway to prevent to have to define globals at all (within the "consuming" scripts).

One can get around the " don't define globals" by using
:local name "foo";
:local value [/system/script/environment/get [/system/script/environment/find name="$name"] value];
but I was wondering if there might be an easier / better looking way...
 
jaclaz
Long time Member
Long time Member
Posts: 667
Joined: Tue Oct 03, 2023 4:21 pm

Re: Retrieveing a global variable readonly to a local variable

Mon Mar 04, 2024 4:37 pm

If I may, it is not particularly easy to read when you use variable names that are also common names or properties.

If I get this right, your snippet, using var_1, var_2 instead of name and value is:

:local var_1 "foo";
:local var_2 [/system/script/environment/get [/system/script/environment/find name="$var_1"] value];
Correct?

But what should it do?
Find that var_1 has a value of "foo" and assign it to var_2?
 
MakroTok
newbie
Topic Author
Posts: 28
Joined: Wed Dec 04, 2019 4:36 pm

Re: Retrieveing a global variable readonly to a local variable

Mon Mar 04, 2024 6:34 pm

If I may, it is not particularly easy to read when you use variable names that are also common names or properties.

If I get this right, your snippet, using var_1, var_2 instead of name and value is:

:local var_1 "foo";
:local var_2 [/system/script/environment/get [/system/script/environment/find name="$var_1"] value];
Correct?

But what should it do?
Find that var_1 has a value of "foo" and assign it to var_2?
Correct. Find the global variable named "foo" (as defined in var_1) and assign its value to var_2.

My use case was to create a DDNS script which could work with multiple services in parallel without the need to store the sync URL within the script itself.
This has some implications:
  • for multiple services one needs multiple configurations
  • to make them distinctive whithout changing the script the varaiable name has to be dynamic
  • to make them dynamic but still relatable use a stable key , e.g. :jobname
  • one cannot use dynamic variable names directly without global variables which then would again interfere with each other...
So my script basically does:
:local serviceName [:jobname];
:local syncURL [/system/script/environment/get [/system/script/environment/find name="$serviceName"] value];
So if my script is executed/stored as "FreeDNS" there will be a global variable "FreeDNS" which can be configured with the respective sync URL.
If the script is executed/stored as "DuckDNS" there will be a global variable "DuckDNS" which can be configured with the respective sync URL.

It's not a business requirement or alike, it's just me playing with stuff. Regarding:
:local syncURL [/system/script/environment/get [/system/script/environment/find name="$serviceName"] value];
This code works for me, but somehow it doesn't look straightforward and requires more permissions than using the :parse approach.
So I was wondering if there might be better ways to do it (but all other ways I came up with required the definition of additional global variables which might interfere with each other...).
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 3509
Joined: Sun May 01, 2016 7:12 pm
Location: California

Re: Retrieveing a global variable readonly to a local variable

Mon Mar 04, 2024 7:39 pm

:global's are just Linux env variable under-the-covers, and there is NOT some /etc/profile that loads :global's – /system/script run in some user context & various other restrictions/rule depending in other place scripts are used (netwatch, dhcp, etc.). But in the end using one :global in another place is possible, just tricky. But I'm not sure about trying to make anything "read only" helps the confusion.

Since we're talking about some fixed URL that needs to be shared between scripts.... Rather than trying to read /system/script/environment to fetch a global... another approach is to "nascent config" to store the needed data. e.g. stuff like /ip/dns/static (with TXT entry), /ppp/secret (with no allowed protocols), /ip/firewall/layer7-protocol (only used by reference in fw rules), etc. etc. can be used to "stash" data for scripts. Since these things are config, they get persisted.

For example, I have a function $SECRET that I used to store API keys for SaaS things. See viewtopic.php?t=183527&hilit=secret#p916159
This $SECRET wraps /ppp/secret to save an API key "semi-securely" (e.g. saved in config, so always available via $SECRET function indirectly or via [/ppp/secret/get ]. Since PPP secret password are require "sensitive" they are not exported and only available to scripts with sensitive policy.

In your DDNS case since URL is like not private, using DNS static TXT entries may work. e.g.
# save url once...
/ip/dns/static/add type=TXT text="http://my-ddns-url" name="_ddns_url"
# get url from a script later...
:put [/ip/dns/static { get [find name="_ddns_url"] text }]

@rextended has another example use Layer7 firewall here: viewtopic.php?t=170591
 
jaclaz
Long time Member
Long time Member
Posts: 667
Joined: Tue Oct 03, 2023 4:21 pm

Re: Retrieveing a global variable readonly to a local variable

Mon Mar 04, 2024 8:17 pm

@Amm0
Not that I need or want to use this kind of trickery, but one could use *any* setting that can be easily found and use the comment field (disabling the setting), i.e. one could use (as an example) a (bogus, disabled) static route or a firewall nat or filter rule?
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 3509
Joined: Sun May 01, 2016 7:12 pm
Location: California

Re: Retrieveing a global variable readonly to a local variable

Mon Mar 04, 2024 8:56 pm

@Amm0
Not that I need or want to use this kind of trickery, but one could use *any* setting that can be easily found and use the comment field (disabling the setting), i.e. one could use (as an example) a (bogus, disabled) static route or a firewall nat or filter rule?
All true. Same concept: use some/any config item/comment/etc if you want it around after a reboot. Even the comment on a /system/script itself, then accessed via :jobname . Lot of options.

Main point was I'm not sure playing masquerade with :local is a good idea/helpful to the underlying problem of "sharing variables".
:local var_1 "foo";
:local var_2 [/system/script/environment/get [/system/script/environment/find name="$var_1"] value];
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 3509
Joined: Sun May 01, 2016 7:12 pm
Location: California

Re: Retrieveing a global variable readonly to a local variable

Mon Mar 04, 2024 9:01 pm

I guess if you want a "readonly global to local", you can use :return in /system/script to get some static data.

e.g.
/system/script/add name=staticUrl source={ :return "http://example.com" } dont-require-permissions=yes

:put [/system/script/run staticUrl]          
# http://example.com

#or actually using a local:
{ :local staticUrl [/system/script/run staticUrl]; :put $staticUrl }
# http://example.com

 
MakroTok
newbie
Topic Author
Posts: 28
Joined: Wed Dec 04, 2019 4:36 pm

Re: Retrieveing a global variable readonly to a local variable

Tue Mar 05, 2024 7:38 pm

@Amm0
Not that I need or want to use this kind of trickery, but one could use *any* setting that can be easily found and use the comment field (disabling the setting), i.e. one could use (as an example) a (bogus, disabled) static route or a firewall nat or filter rule?
All true. Same concept: use some/any config item/comment/etc if you want it around after a reboot. Even the comment on a /system/script itself, then accessed via :jobname . Lot of options.
For my use case (and because I need just one single value) the idea with the comment is actually really awesome. :-D

Thanks!

Who is online

Users browsing this forum: MSN [Bot], Nullcaller and 13 guests