6

In order to get my setup a bit closer to "one click deployment", I would like to use groovy scripts to start/stop other processes controlled by bat scripts, running in different parts of the filesystem and even on different machines.

How to execute these scripts and how to do it from their respective working directory?

I know Java's

java.lang.Runtime's exec()

However there are lots of issues with this and I wondered if Groovy had some kind of shorthand for this as well?

Thanks!

raoulsson
  • 14,978
  • 11
  • 44
  • 68

4 Answers4

11

Groovy added an execute() method to plain old String, so try this:

println "ls -la".execute().text
John Flinchbaugh
  • 2,338
  • 1
  • 17
  • 20
9

The execute() method can be used to change directories if you prefix it with the "cmd /c" command, and then use ampersand (assuming Windows) to chain commands together.

Example, assuming you want to go to subdirectory subdir and run a couple of batch files from there:

println "cmd /c cd subdir & batch1.bat & batch2.bat".execute().text

Not sure if there isn't a better way, but this does work.

seansand
  • 1,492
  • 4
  • 18
  • 23
  • for something similar on a Linux system you might need to do a variant like this: [ 'sh', '-c', 'your-commands-here'].execute().text - whilst on Windows systems command parsing of a single string is already in there under the hood (it might or might not be part of the api spec.) – Alexander Stohr Jan 26 '21 at 15:55
1

You can also use ProcessBuilder which is a surprisingly convienent Java class introduced in java 5.

ProcessBuilder lets you

  • determine the working directory
  • determine which environmental variables the process should have

See http://download.oracle.com/javase/1.5.0/docs/api/java/lang/ProcessBuilder.html for a brief example and more documentation.

Marco
  • 8,958
  • 1
  • 36
  • 56
  • I second that. Here's [a blog post](http://www.joergm.com/2010/09/executing-shell-commands-in-groovy/) that combines Groovy and the ProcessBuilder – FabienB Jan 27 '15 at 13:45
0

If you aren't afraid to create some reusable code you could create an object that wraps an .execute() process. I created something like this and use it regularly.

Create a new process with:

def proc="cmd".execute()

After that you can use "consumeProcessOutput()" to manage the input and output of "proc". Anything you send to it will be acted on as though you typed it into a shell, and all the output of that shell will be available to you.

I wrapped all this up in a closure so that you could do this:

cmd("cd \\ \n dir ") {
    if(it.contains("AUTOEXEC.BAT")) 
        println it;
    return true;
}

To get a display that shows only the autoexec.bat line. Note that until you return true from the closure, the stdin of that process is available so you can send more lines of text and interact with it indefinitely.

I use it quite a bit because commands like "cd" and "Dir" don't work in windows with .execute(), so a simple:

def directoryListing=cmd("cd\\\ndir")

will get me a quick directory listing with ease.

Bill K
  • 62,186
  • 18
  • 105
  • 157