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.)
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…
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 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:
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…).
: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 http://forum.mikrotik.com/t/securely-storing-apikey-tokens-for-tool-fetch-approaches-secret/156066/1
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 }]
@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”.