Community discussions

MikroTik App
 
pe1chl
Forum Guru
Forum Guru
Topic Author
Posts: 10186
Joined: Mon Jun 08, 2015 12:09 pm

How to get command output inside a script without printing it to the terminal?

Mon Jan 30, 2023 12:02 pm

I want to get the output of a "print" command inside a script into a variable. The [/command/print] construct gets the output in the variable, but it still also prints it.
E.g.:
/routing/bgp/session {
   :local prefixes;
   :foreach ses in=[find] do={
      :set $name [get $ses name]
      :set $remote [get $ses "remote.address"]
      :set $prefix [/routing/route/print count-only  where belongs-to="bgp-IP-$remote"]
      :set ($prefixes->$name) $prefix
   }
   :foreach name,prefix in=$prefixes do={
      :put "$name: $prefix"
   }
}
This script walks the active session list of BGP and reads the number of prefixes received on each of them (due to lack of RouterOS v7 providing this in the session info).
The script works OK (as of RouterOS 7.8beta2), but before it outputs the alphabetically sorted list of BGP peers and their prefixes, it first prints the prefix numbers in the random order the sessions are in the list. That is because the
:set $prefix [/routing/route/print count-only  where belongs-to="bgp-IP-$remote"]
not only puts the value in $prefix but also outputs it to the terminal.
How can I suppress that?
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11968
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: How to get command output inside a script without printing it to the terminal?

Mon Jan 30, 2023 1:11 pm

I do not reach to test belongs-to: no one value with count-only work on 7.7

Without count-only work as expected:

Work
/routing/route/print where belongs-to="bgp-IP-xxx.xxx.xxx.xxx"

Do not work
/routing/route/print count-only where belongs-to="bgp-IP-xxx.xxx.xxx.xxx"

This work, and do not print nothing on terminal:
:put [:len [/routing route find where belongs-to="bgp-IP-xxx.xxx.xxx.xxx"]]
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11968
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: How to get command output inside a script without printing it to the terminal?

Mon Jan 30, 2023 1:27 pm

I want to get […]

Check this if it's good enough:

revised only v7 code

/routing/bgp/session
{
    :local prefixes ({})
    :foreach session in=[find] do={
        :local belongs [get $session "remote.address"]
        :if ([:typeof $belongs]="ip") do={:set belongs "bgp-IP-$belongs"}
        :if ([:typeof $belongs]="ip6") do={:set belongs "bgp-IP6-$belongs"}
        :set ($prefixes->[get $session name]) [:len [/routing/route find where belongs-to=$belongs]]
    }
    :foreach name,prefix in=$prefixes do={
        :put "$name: $prefix"
    }
}
 
pe1chl
Forum Guru
Forum Guru
Topic Author
Posts: 10186
Joined: Mon Jun 08, 2015 12:09 pm

Re: How to get command output inside a script without printing it to the terminal?

Mon Jan 30, 2023 3:41 pm

I know that that works, but it is extremely inefficient.
In 7.8beta2 (as I wrote) the "count-only where..." works OK and is a lot faster than fetching all the routes in an array and counting the members.
I am not looking for "how can I get the result in a different way" but for "how can I catch the output in a variable without it also appearing on the terminal".
That is a general issue that could also become relevant in other contexts.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11968
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: How to get command output inside a script without printing it to the terminal?

Mon Jan 30, 2023 4:06 pm

"how can I catch the output in a variable without it also appearing on the terminal".

Try this...

for v7.8beta2 only code

:global tmpvar 0
/routing/bgp/session
{
    :local prefixes ({})
    :foreach session in=[find] do={
        :local belongs [get $session "remote.address"]
        :if ([:typeof $belongs]="ip") do={:set belongs "bgp-IP-$belongs"}
        :if ([:typeof $belongs]="ip6") do={:set belongs "bgp-IP6-$belongs"}
        :local jobID [:execute ":global tmpvar [/routing/route print count-only where belongs-to=\"$belongs\"]"]
        :while ([:len [/system/script/job find where .id=$jobID]] > 0) do={:delay 1s}
        :set ($prefixes->[get $session name]) $tmpvar
    }
    :foreach name,prefix in=$prefixes do={
        :put "$name: $prefix"
    }
}
:set tmpvar
 
pe1chl
Forum Guru
Forum Guru
Topic Author
Posts: 10186
Joined: Mon Jun 08, 2015 12:09 pm

Re: How to get command output inside a script without printing it to the terminal?

Mon Jan 30, 2023 7:16 pm

I consider that "too dirty".
I hope there is a real solution...
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11968
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: How to get command output inside a script without printing it to the terminal?

Mon Jan 30, 2023 7:17 pm

You are insatiable... :lol: :lol: :lol:
 
pe1chl
Forum Guru
Forum Guru
Topic Author
Posts: 10186
Joined: Mon Jun 08, 2015 12:09 pm

Re: How to get command output inside a script without printing it to the terminal?

Mon Jan 30, 2023 7:26 pm

I will make a ticket. But currently the service desk server is down.
 
User avatar
pkt
just joined
Posts: 14
Joined: Tue Jan 24, 2023 10:12 pm
Location: /u/mw/ss/e/eu/es

Re: How to get command output inside a script without printing it to the terminal?

Mon Jan 30, 2023 9:24 pm

:set $prefix [/routing/route/print count-only  where belongs-to="bgp-IP-$remote"]
not only puts the value in $prefix but also outputs it to the terminal.
How can I suppress that?

I think this is done with as-value.
Code will be:
:set prefix [/routing/route/print as-value count-only where belongs-to="bgp-IP-$remote"];
but nevertheless this also outputs it to terminal. Seems a bug when using as-value combined with count-only.

Instead, using as-value with bare print output works well:
[admin@MikroTik] > /routing/route/print where dst-address~"111"
Flags: A - ACTIVE; c, y - COPY
Columns: DST-ADDRESS, GATEWAY, AFI, DISTANCE, SCOPE, IMMEDIATE-GW
   DST-ADDRESS       GATEWAY        AFI  DISTANCE  SCOPE  IMMEDIATE-GW 
Ac 192.168.111.0/24  bridge-switch  ip4         0     10  bridge-switch
Usual print output.

[admin@MikroTik] > [/routing/route/print as-value where dst-address~"111"]
No :put, so no output, as expected.

[admin@MikroTik] > :local var [/routing/route/print as-value where dst-address~"111"]; :put $var
.id=*20144018;afi=ip4;distance=0;dst-address=192.168.111.0/24;gateway=bridge-switch;immediate-gw=bridge-
switch;scope=10
Output via :put, as expected.
 
pe1chl
Forum Guru
Forum Guru
Topic Author
Posts: 10186
Joined: Mon Jun 08, 2015 12:09 pm

Re: How to get command output inside a script without printing it to the terminal?

Mon Jan 30, 2023 9:38 pm

Thank you for the hint! Now I seem to remember as-value but the docs of scripting are so inaccessible...
Indeed, it appears the combination of "as-value" and "count-only" does not work...
It looks like the programmer of the new routing was no well integrated with RouterOS conventions, the parameter structure is also very different from tradition.
 
pe1chl
Forum Guru
Forum Guru
Topic Author
Posts: 10186
Joined: Mon Jun 08, 2015 12:09 pm

Re: How to get command output inside a script without printing it to the terminal?

Mon Jan 30, 2023 9:55 pm

Created #[SUP-106245]: count-only output always goes to terminal even when as-value is specified
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11968
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: How to get command output inside a script without printing it to the terminal?

Mon Jan 30, 2023 11:07 pm

I do not suggest you as-value + [:len ] because...
In 7.8beta2 (as I wrote) the "count-only where..." works OK and is a lot faster than fetching all the routes in an array and counting the members.
Yes, count-only and as-value are on conflict...
 
zainarbani
Frequent Visitor
Frequent Visitor
Posts: 54
Joined: Thu Jul 22, 2021 9:42 am
Location: Pati, Indonesia

Re: How to get command output inside a script without printing it to the terminal?

Tue Jan 31, 2023 2:28 pm

In 7.8beta2 (as I wrote) the "count-only where..." works OK and is a lot faster than fetching all the routes in an array and counting the members.
How about find+len?, since find only return obj ID.
Not sure about task speed.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11968
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: How to get command output inside a script without printing it to the terminal?

Tue Jan 31, 2023 2:48 pm

How about find+len?, since find only return obj ID.
Not sure about task speed.
Already solved on two way, on post #3, and on post #5, but user reply with this to numer #3:
viewtopic.php?t=193118#p980987
and this for post #5
viewtopic.php?p=981231#p981080

Before write a post, is better read all topic...
 
zainarbani
Frequent Visitor
Frequent Visitor
Posts: 54
Joined: Thu Jul 22, 2021 9:42 am
Location: Pati, Indonesia

Re: How to get command output inside a script without printing it to the terminal?

Tue Jan 31, 2023 2:59 pm

Already solved on two way, on post #3, and on post #5, but user reply with this to numer #3:
viewtopic.php?t=193118#p980987
and this for post #5
viewtopic.php?p=981231#p981080

Before write a post, is better read all topic...
My bad :lol:
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11968
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: How to get command output inside a script without printing it to the terminal?

Fri Feb 03, 2023 6:31 pm

On 7.8beta3 :execute is broken on purpose?....

Fix

from 7.8beta3 code

:global tmpvar 0
/routing/bgp/session
{
    :local prefixes ({})
    :foreach session in=[find] do={
        :local belongs [get $session "remote.address"]
        :if ([:typeof $belongs]="ip") do={:set belongs "bgp-IP-$belongs"}
        :if ([:typeof $belongs]="ip6") do={:set belongs "bgp-IP6-$belongs"}
        :local jobID [:execute ":global tmpvar [/routing/route print count-only where belongs-to=\"$belongs\" \
                               file=/useless_change_that_broke_the_balls]]"
        :while ([:len [/system/script/job find where .id=$jobID]] > 0) do={:delay 1s}
        :set ($prefixes->[get $session name]) $tmpvar
    }
    :foreach name,prefix in=$prefixes do={
        :put "$name: $prefix"
    }
}
:set tmpvar
Last edited by rextended on Fri Feb 10, 2023 6:01 pm, edited 1 time in total.
 
pe1chl
Forum Guru
Forum Guru
Topic Author
Posts: 10186
Joined: Mon Jun 08, 2015 12:09 pm

Re: How to get command output inside a script without printing it to the terminal?

Thu Feb 09, 2023 12:10 pm

My SUP ticket was answered with "There will be major console improvements in the near future, we will include this feature too."
So there is hope that we will soon see some improvement.

Who is online

Users browsing this forum: aoravent, Ellaham and 24 guests