This film could have ended much differentlyif Jerry were running Cumulus Linux |
In the bash shell, tab completion capabilities are usually limited to helping complete:
- shell built-in commands
- external executables found in $PATH
- file names
- directory names
Completion in bash doesn't help with things like command line arguments to various commands, but it is (sometimes) smart enough to not offer filenames as completion options to the 'cd' command, choosing instead to only offer directories.
Network devices, on the other hand, tend to have really rich inline help / command completion stuff, and I live by it.
Rather than typing abbreviated commands, I prefer to let the system help me type the whole thing, partly because it eliminates errors, and partly because I usually can't remember the exact syntax for a given platform. Cisco's godawful platform-dependent mac-address-table vs. mac address-table comes immediately to mind as something that always seems to take more than one attempt.
So, rather than typing this:
ROUTER#sh ip bg vpnv4 vr GREEN nei A.B.C.D received-
I tend to do this:
ROUTER#sh<TAB>
ROUTER#show ip bg<TAB>
ROUTER#show ip bgp vp<TAB>
ROUTER#show ip bgp vpnv4<TAB>
ROUTER#show ip bgp vpnv4 vr<TAB>
ROUTER#show ip bgp vpnv4 vrf GREEN nei<TAB>
ROUTER#show ip bgp vpnv4 vrf GREEN neighbors A.B.C.D re<TAB>
ROUTER#show ip bgp vpnv4 vrf GREEN neighbors A.B.C.D received-<TAB>
ROUTER#show ip bgp vpnv4 vrf GREEN neighbors A.B.C.D received-routes
This is pretty helpful, and an improvement over the bash shell where you often must abandon the command line for man pages in order to figure out the options for a given command.
Imagine my surprise when I found myself using pretty-full-featured tab completion in Cumulus Linux!
For example, when I started up the routing services for the first time, I instinctively did this:
#serv<TAB>Checking the CDP/LLDP neighbors table also supports completion:
#service qu<TAB>
#service quagga sta<TAB>
#service quagga start
#lldp<TAB>
#lldpcli nei<TAB>
#lldpcli neighbor sh<TAB>
#lldpcli neighbor show
If I wasn't sure about an argument, or if more than one argument matched, a second press of <TAB> offered the whole list of possibilities in the way you'd expect from bash, similar to the '?' on Cisco IOS.
This is really nice, and so seamlessly integrated that I didn't even notice I was using it at first. Then I noticed, and was mystified: What is this wizardry?
Well, here's how it works.
Suppose we've got an executable mycommand, which understands two arguments "-A" and "-B".
In order to get bash completion for mycommand, we need to drop a bash completion script in /etc/bash_completion.d/ (a directory I'd never even noticed before.) The script should get sourced by your shell at startup time, and it does two things:
- It loads a module into the shell.
- It associates the module with the command in question for completion purposes.
So, here's a simple example, for mycommand.
[chris@poetaster]$ cat /etc/bash_completion.d/mycommand.bash
_mycommand()
{
COMPREPLY=( $(compgen -W "-A -B" -- ${cur}) )
return 0
}
complete -F _mycommand mycommand
[chris@poetaster]$
Now, we're rewarded with the following:
[chris@poetaster]$ myc<TAB>
[chris@poetaster]$ mycommand <TAB>
[chris@poetaster]$ mycommand -<TAB>
<audible bell>
[chris@poetaster]$ mycommand -<TAB>
-A -B
[chris@poetaster]$ mycommand -A
Unlike Cisco IOS, the bash prompt in Cumulus Linux executes completion without printing extraneous lines, which I appreciate.
Of course, the completion routines baked into CumulusLinux are much more complicated than my simple "-A -B" example here. They understand the context of the command, where files are required vs. switches, when one option makes another obsolete, interface names, ip addresses, etc...
The completion feature wasn't mentioned in any of the documentation I read. It's a small thing, and they just did it without making a big deal. But it's really helpful, and I think it will help make lots of network folks much more comfortable in the Linux shell than they might otherwise have been.
Also, I'm glad they did it because I had no idea this existed, and I'm already thinking about ways to bake it into stuff I work on every day. Particularly virsh. I want command completion to help me type the names of VMs.