Interactive bash Scripts

Building interactive commands that uses editing history and tab completion can be easy in bash and serve as a wrapper for automating tasks.

Now that you’ve mastered the command line fu using .inputrc as described in a previous post, you’d like to use this in building other tools..

I’ve used this basic technique in scripts for automating deployments, monitoring and possible rollbacks for hundreds or thousands of hosts, but today I’d like to describe it using a “toy” example so that you can see how easy it is. It basically involves building a “read/eval” loop in your shell script.

The example I’ve chosen it to build a simple persistent history editing and tab completion facility into “bc”, with an added bonus of being able to use expressions with the “factor” application. Now in reality, “bc” is often already compiled with readline now; but the history isn’t written to a file (and it doesn’t have “factor” support).

How It Works

The script can be downloaded here:  bcw github repo

We first set up a temporary directory where we’ll touch some files that are used for tab completion. We then read in the persistent history file if it exists and drop into a read/eval loop where the commands are interpreted.

While we are reading the command, we temporarily cd into the tab completion directory to facilitate users entering partial commands and using tab to complete. (This directory can be dynamically updated as well which I’ve used that in more complicated situations.)

Example Session

In this session, I’ll add some comments which are relevant if you have “set editing-mode vi” set in your $HOME/.inputrc file. If you don’t have that set, then you’re on your own.. (You can still edit the command line history, just not using “vi” key bindings.)

 


 

twiggy:~/git/bcw$ grep editing-mode ~/.inputrc
set editing-mode vi
twiggy:~/git/bcw$ bcw
[bcw]->help
Help:
  expr expression     # feed expression through bc
  factor expression   # factor the expression
  history             # list the history
  history clear       # clear history
  sh                  # head out to the shell (exit or ^D to return)
  sh command          # run command outside of bcw
  debug   [on|off]    # examine or change debug
  trace   [on|off]    # examine or change trace
  verbose [on|off]    # examine or change verbose
  clear               # clear clutter
[bcw]->sh pwd
/Users/bduncan/git/bcw
[bcw]->expr 2^31-1
2147483647
[bcw]-># roll back and edit using "kcefac[tab]"
[bcw]->factor 2^31-1
2147483647: 2147483647
[bcw]->exponent=19
[bcw]-># roll back and edit using "kkf3ce$exponent"
[bcw]->factor 2^$exponent-1
524287: 524287
[bcw]-># roll back and edit using "kceecho"
[bcw]->echo 2^$exponent-1
2^19-1
[bcw]->debug
debug is off
[bcw]->debug on
[bcw debug]->factor 2^$exponent-1
docommand [factor 2^$exponent-1]
524287: 524287
[bcw debug]->debug off
docommand [debug off]
[bcw]->ibase=2
[bcw]-># 2^18-1
[bcw]->factor 111111111111111111
262143: 3 3 3 7 19 73
[bcw]-># roll back and edit using "kA1"
[bcw]->factor 1111111111111111111
524287: 524287
[bcw]-># control-D to exit
[bcw]->Bye!

 


Summary

I’ve used the technique to hide details for operating on groups of large numbers of hosts in parallel, keeping track of all operations and verifying them. Use your Imagination and build your own interactive commands leveraging your command line history editing kung fu!

 

Leave a Reply

Your email address will not be published. Required fields are marked *