netlab: Execute a Command on Multiple Devices
When I was updating the Network Migration with BGP Local-AS Feature blog post, I wanted to execute the same command (show ip bgp) on all routers in my network.
Not a problem: since Dan Partelly added the netlab exec command, it’s as simple as netlab exec * show ip bgp. Well, not exactly; there are still a few quirks.
The easy one first: any decent Unix shell thinks it should expand the *
in the command line, resulting in a command that includes every filename in the current directory. Not exactly helpful; we have to quote the *
to make the command work:
$ netlab exec '*' show ip bgp
netlab exec r*
works but netlab exec *
does not.
Here are the first few lines produced by the above command:
Connecting to clab-LocalAS_Migr-custa using SSH port 22, executing show ip bgp
BGP table version is 4, local router ID is 10.0.0.4
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter,
x best-external, a additional-path, c RIB-compressed,
t secondary path, L long-lived-stale,
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
*> 10.6.6.0/24 10.1.0.10 0 64510 64500 i
*> 10.8.8.0/24 0.0.0.0 0 32768 i
*> 10.9.9.0/24 10.1.0.10 0 64510 65100 iConnection to clab-localas_migr-custa closed by remote host.
We have the results we need, but they’re full of noise. For example, we should get rid of the BGP table legend. We can use the | begin Network
filter on Cisco IOS to do that, but it’s a bit hard to add that filter to a bash command without starting a Linux pipe. Fortunately, we can quote the |
symbol:
$ netlab exec '*' show ip bgp \| begin Network
Connecting to clab-LocalAS_Migr-custa using SSH port 22, executing show ip bgp | begin Network
Network Next Hop Metric LocPrf Weight Path
*> 10.6.6.0/24 10.1.0.10 0 64510 64500 i
*> 10.8.8.0/24 0.0.0.0 0 32768 i
*> 10.9.9.0/24 10.1.0.10 0 64510 65100 iConnection to clab-localas_migr-custa closed by remote host.
It would also be nice to get rid of the Connecting to… header but still retain some information about the device on which we’re executing the command. Let’s use the -q
(quiet) flag together with the --header
flag:
$ netlab exec -q --header '*' show ip bgp \| begin Network
================================================================================
custa: executing show ip bgp | begin Network
================================================================================
Network Next Hop Metric LocPrf Weight Path
*> 10.6.6.0/24 10.1.0.10 0 64510 64500 i
*> 10.8.8.0/24 0.0.0.0 0 32768 i
*> 10.9.9.0/24 10.1.0.10 0 64510 65100 iConnection to clab-localas_migr-custa closed by remote host.
Finally, there’s the annoying “Connection closed by remote host” message appended at the end of the last line. I couldn’t get rid of it (and StackOverflow and friends were no help) or persuade Cisco IOS to terminate the last line with a newline; if you have an idea, please add a comment.
ssh -o RequestTTY=no [email protected]
(couldn't test because I don't have access to IOS and FRR doesn't have this issue)
> Did you try...
Thanks a million, but it doesn't work. Also, the problem seems to be limited only to IOL containers. IOSv VM (or Aruba CX running in a container) behaves as expected.
Why not avoiding bash collisions using better args? - Named args instead of positionals - 'all' to mean '*' for basic usages, while keeping support for glob (maybe even add regex support for advanced use cases) - 'internal pipes' AND external bash pipes
Eg: netlab exec --target all --command 'show ip bgp | begin Network' | egrep -v... | sed...
Btw, there are 1file libs that help building cli tools very easily, like https://github.com/bDgcgsX4bnc3Duprdb2S/funcli (1 file, no dependency, you get the idea)
Well, I was aiming for the simplicity of "ssh host command", but I like the "--command" idea.
As for "all", that's a great idea and I could add device names as groups, so you could execute (for example) the same command on all the IOS devices in your lab.
Thanks a million for the suggestions!