software development for the
existentially challenged
Older | Newer Older | Newer
Groovy Shell Scripting
comment share
As we all know, Groovy is an awesome scripting language. Unfortunately it's not always clear from the documentation wiki how to get the job done. Here are a few thoughts. These comments are fairly unix-centric, though you can glean something if you're using a Windows DOS shell (yeah, I know it's not DOS anymore, but you know what, it's still DOS). If you're using Windows, get cygwin.

A lot of what's here is more or less out there already in a variety of spots, but I wanted to share some info that a friend of mine and I ground through today.

Create a script file somewhere, say in a bin directory in your home directory.
/Users/tpierce/bin
[file foobly.groovy]
println "do some groovy stuff"
One way to execute it is
groovy foobly.groovy
(You have to have your groovy executable on your PATH)

Even better, you can use groovy as a first class scripting language. Add this to the top of your file:
#!/usr/local/bin/groovy
println "do some groovy stuff"
The hash-bang header instructs unix to use the executable in the header when the script is invoked on the command line. Of course, the path in the header needs to actually point to your groovy shell executable.

Next, make the script executable:
chmod +x foobly.groovy
then simply invoke as:
./bin/foobly.groovy
To be extra slick, drop .groovy, add $HOME/bin to your path, and you can just say
foobly
from anywhere.

You can get extra power by making unix tool env as your #! executable. This allows you to easily pass through shell variables and to add additional environmental variables in the header like so:
#!/usr/bin/env VAR1=value1 VAR2=value2 groovy
To provide access to your classpath, add -cp to your groovy invocation:
#!/usr/bin/env groovy -cp /path/to/jars/myjar.jar
Of course, you don't have to put just jars on the classpath. If you add a directory with other groovy files and your script references them, groovy will compile them as well and provide them for use.
#!/usr/bin/env groovy -cp /Users/tpierce/bin
Using env, because environmental variables are getting passed to your header, you can do stuff like this:
#!/usr/bin/env groovy -cp ${HOME}/bin
In general, everything seems to work as you'd expect. One major irk: if you have a class defined within a script file, groovy will not recognize it. To be more precise, if your class has a different name from the script file's name.

For instance:

[file foo.groovy]
#!/usr/bin/env groovy -cp .
println "some stuff happens here"

class Bar {
Bar() {println "starting bar"}
}
Execute foo.groovy:
lunchtruck:bin tpierce$ ./foo.groovy 
some stuff happens here
Everything is good. Now, define a second file using Bar

[file chumbly.groovy]
#!/usr/bin/env groovy -cp .
new Bar()
And execute:
lunchtruck:bin tpierce$ ./chumbly.groovy 
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed,
/Users/tpierce/bin/chumbly.groovy: 2: unable to resolve class Bar 
 @ line 2, column 1.
   new Bar()
   ^

1 error
Not so good. This fails at because Bar isn't in a file with the same name as the class, so it doesn't get dynamically compiled. I've seen reference to there being a shortcoming of the GroovyScriptEngine class that keeps it from compiling classes inside of scripts. I don't know that that's what's causing this, but I'd suspect that's it.

You're better off keeping your classes in the standard Java, one class per file, configuration.

There's some other stuff I haven't really thought through, like defining in a clever way the classpath within the file. If you change the location of your jars or your scripts you really don't want to have to touch the #! line of every script you've written.

Hopefully that's helpful to anyone trying to use groovy as a the awesome scripting language that it is.

1 comments:

Spina said...

Thanks for the tips! Groovy is easily my favorite scripting language.

To extend your thoughts above about classpaths, you can use the @grab annotation in a Groovy script to describe the required Jars. Then at runtime they're retrieved using Ivy. This will make your script much more portable. Yay! See here:

http://groovy.codehaus.org/Grape

Post a Comment

What is this site?!

t (a professional software developer for a big company) writes about software development and stuff. Unix, Java, Groovy, OS X, and lots of open source libraries and tools.