You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@geronimo.apache.org by Jason Dillon <ja...@planet57.com> on 2006/05/28 23:03:42 UTC
GShell (longish)
Some of you may have noticed some commits to the sandbox for
GShell... but just what is this GShell thingy? I've been meaning to
put some words to this on the dev list for a while... so here goes.
GShell is the second coming of Twiddle (3rd if you count the first
iteration I did for a certain other app server). But what the heck
is Twiddle? Well, over the years I have realized that I spend way to
much time writing framework around command-line tools, just to get a
simple task accomplished. And each time I need to add a tiny other
little feature I end up doing it all over again. Twiddle was
intended to be a simple framework for implementing command-line
tools, where only the functionality needs to be implemented, none of
the plumbing.
But what plumbing is there for command-line tools? Well, that
becomes more apparent when you start to think about how commands
(plural) can coexist and cooperate together. At that point you have
the commands option parsing and functionality... plus interaction
with input/output streams and environment variables, etc.
<rant>
But Jason, why not use use the system's shell for this stuff? Well,
as many of you know... the Windows cmd.exe sucks ass, and despite the
profits of vista hoping that ms-foolios are going to fix it, I can't
assume they will, since they have had years to pull their heads out
and see the folly of batch.
</rant>
But, more so... I want to be able to SSH into my application server
and run those commands. I want to be able to launch a script
(language of my choice) in the server from a remote terminal and have
it just work as I would expect it to. IMO that is really where the
benefit of the common plumbing is.
Yet even before we get there, the plumbing allows for use to build
simple and *consistent* command-line tools. Adding a new tool is as
simple as adding a new jar to a directory, no need for more scripts
to maintain, or configuration files, yada yada.
Another key facet to GShell is (or will be) its ability to load
command sets into categories. This is basically a namespace not
unlike a directory in normal-shell terms, which a set of related
commands exit. For example, all 'jmx' command can be organized in
the a 'jmx' category, etc.
* * *
Anyways, so what I have done so far is... I dug up the old Geronimo
Twiddle code from CVS, and started re-implementing... and in comes
GShell.
Initially I was using Spring to wire up command prototypes... then
after talking to David Blevins I started looking into using the
ResourceFinder to dynamically find property files. Currently the
impl is in-between both, as I'm still wrestling for how to make use
of IoC to configure components in the lightest possible fashion.
So, I've shelved some of that plumbing and moved on to the
interactive console bits. I've always wanted Readline/Editline-like
support, but never liked the native requirements. And then a few
weeks ago I found JLine ( http://jline.sourceforge.net/ ), which at
least on Unix does not require any native libs (though does exec
stty). Anyways, the result is that you can run GShell out of the box
and get Readline/Editline support for a rich command-line
experience. Not sure yet how JLine is going to play with SSH/Telnet
streams, but I think that can wait until later.
Still unsure about the IoC bits, I moved on to piecing together a
parser which will take a single or multiline string and convert that
into a tree structure representing the command-line to be executed.
I'm trying for something that can handle most things that BASH or ZSH
can (leaning towards ZSH since it kicks ass all over BASH).
This is currently where I am at now... with just the very basics of a
parser in place, some command-discovery currently done via
ResourceFinder... but no IoC, and a simple JLine console and some
example commands.
* * *
So what can GShell do now? Um, some... but not that much.
I've put together the basic build system, which by default will spit
out an assembly archive with all of the standard and extension
commands configured. The one caveat is that you must build xbean/
trunk/xbean-finder first, since that is not yet published anywhere.
But you can:
svn co https://svn.apache.org/repos/asf/geronimo/sandbox/gshell/
trunk/ gshell
cd gshell
mvn
gunzip -c gshell-assembly/target/gshell-1.0.0-SNAPSHOT-bin.tar.gz |
tar xf -
./gshell-1.0.0-SNAPSHOT/bin/gshell
At this point you've got a GShell running (and on Unix you should get
a nice jline interface, windows too but that has not been tested).
Standard commands that are implemented are:
echo
cat
exit
java
set
help (broken currently)
Extended commands:
script
All commands take a '--help' or '-h' to spit out what they can do and
how you configure them to do it. As mentioned help is broken, as it
was based on the Spring impl to discover commands, pending some work
on how to use IoC (or not) to find all commands.
> echo --help
echo -- write arguments to the commands output
usage: echo [options] [string ...]
-h,--help Display this help message
-n Do not print the trailing newline character
> cat --help
cat -- concatenate and print files
usage: cat [options] [file ...]
-h,--help Display this help message
-n Number the output lines, starting at 1
> exit --help
exit -- exit the virtual machine
usage: exit [options]
-c,--code Use the given exit code
-h,--help Display this help message
> java --help
java -- execute a java application
usage: java [options] <classname> [arguments]
-M,--method Invoke a named method
-h,--help Display this help message
> set --help
set -- set a variable or property
usage: set [options] <name=value>
-h,--help Display this help message
help (broken currently)
> script --help
script -- scripting language integration
usage: script [options]
-e,--expression Evaluate the given expression
-h,--help Display this help message
-i,--interactive Run interactive mode
-l,--lang Specify the scripting language
The script command is a simple front-end to BSH, which will if you
add a BSH engine jar to lib/* will allow you to invoke an interactive
(jshell) interpreter or evaluate an expression. Eventually it will
be able to execute a script from a URL or pipe when the parser bits
are finished.
NOTE: Command syntax subject to change ;-)
* * *
What's next? Well, still gotta figure out the IoC bits, which
container, no container, etc. Gotta finish the parser, and figure
out how to line pipelines (ie. echo "foo" | cat -).
Need to get the command context and environment settled. One option
I am leaning towards is allowing the command environment (command
variables that is) to deal with objects not just strings. This makes
the entire environment much more rich. For example, a JMX 'connect'
command could return a Connection object, which could be assigned to
'jmx.connection' variable, and then subsequently JMX commands could
reuse that object. As in:
> jmx.connection=`jmx/connect service:jmx:whatever`
> jmx/invoke mydomain:name=App operation1
> jmx/invoke mydomain:name=App operation2
Here, operation1 and operation2 both use the connection that was set
to the variable 'jmx.connection'. 'jmx.connection' is the default
variable, but could be specified by:
> jmx/invoke -c ${connection} mydomain:name=App operation1
Anyways, the point is that instead of commands taking a String[] and
returning an int, which is modeled after Unix commands, that they
take an Object[] and return an Object. This could mimic the unix
style, but also opens the doors to some fairly larger possibilities.
* * *
Um, okay... enough I think for now ;-)
Anyone who made it this far and know about JavaCC using JJTree want
to drop some knowledge on how best to get the shell grammar parsed?
Its been years since I was using JavaCC, its slowly coming back to
me, but I could use a hand if one is available.
Questions and comments are welcome.
Cheers,
--jason