Groovy executing shell commands

Groovy

Groovy Problem Overview


Groovy adds the execute method to String to make executing shells fairly easy;

println "ls".execute().text

but if an error happens, then there is no resulting output. Is there an easy way to get both the standard error and standard out? (other than creating a bunch of code to; create two threads to read both inputstreams, then using a parent stream to wait for them to complete then convert the strings back to text?)

It would be nice to have something like;

 def x = shellDo("ls /tmp/NoFile")
 println "out: ${x.out} err:${x.err}"

Groovy Solutions


Solution 1 - Groovy

Ok, solved it myself;

def sout = new StringBuilder(), serr = new StringBuilder()
def proc = 'ls /badDir'.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println "out> $sout\nerr> $serr"

displays:

out> err> ls: cannot access /badDir: No such file or directory

Solution 2 - Groovy

"ls".execute() returns a Process object which is why "ls".execute().text works. You should be able to just read the error stream to determine if there were any errors.

There is a extra method on Process that allow you to pass a StringBuffer to retrieve the text: consumeProcessErrorStream(StringBuffer error).

Example:

def proc = "ls".execute()
def b = new StringBuffer()
proc.consumeProcessErrorStream(b)

println proc.text
println b.toString()

Solution 3 - Groovy

// a wrapper closure around executing a string                                  
// can take either a string or a list of strings (for arguments with spaces)    
// prints all output, complains and halts on error                              
def runCommand = { strList ->
  assert ( strList instanceof String ||
           ( strList instanceof List && strList.each{ it instanceof String } ) \
)
  def proc = strList.execute()
  proc.in.eachLine { line -> println line }
  proc.out.close()
  proc.waitFor()

  print "[INFO] ( "
  if(strList instanceof List) {
    strList.each { print "${it} " }
  } else {
    print strList
  }
  println " )"

  if (proc.exitValue()) {
    println "gave the following error: "
    println "[ERROR] ${proc.getErrorStream()}"
  }
  assert !proc.exitValue()
}

Solution 4 - Groovy

I find this more idiomatic:

def proc = "ls foo.txt doesnotexist.txt".execute()
assert proc.in.text == "foo.txt\n"
assert proc.err.text == "ls: doesnotexist.txt: No such file or directory\n"

As another post mentions, these are blocking calls, but since we want to work with the output, this may be necessary.

Solution 5 - Groovy

To add one more important information to above provided answers -

For a process

def proc = command.execute();

always try to use

def outputStream = new StringBuffer();
proc.waitForProcessOutput(outputStream, System.err)
//proc.waitForProcessOutput(System.out, System.err)

rather than

def output = proc.in.text;

to capture the outputs after executing commands in groovy as the latter is a blocking call (SO question for reason).

Solution 6 - Groovy

def exec = { encoding, execPath, execStr, execCommands ->

def outputCatcher = new ByteArrayOutputStream()
def errorCatcher = new ByteArrayOutputStream()

def proc = execStr.execute(null, new File(execPath))
def inputCatcher = proc.outputStream

execCommands.each { cm ->
    inputCatcher.write(cm.getBytes(encoding))
    inputCatcher.flush()
}

proc.consumeProcessOutput(outputCatcher, errorCatcher)
proc.waitFor()

return [new String(outputCatcher.toByteArray(), encoding), new String(errorCatcher.toByteArray(), encoding)]

}

def out = exec("cp866", "C:\\Test", "cmd", ["cd..\n", "dir\n", "exit\n"])

println "OUT:\n" + out[0]
println "ERR:\n" + out[1]

Solution 7 - Groovy

command = "ls *"

def execute_state=sh(returnStdout: true, script: command)

but if the command failure the process will terminate

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBob HerrmannView Question on Stackoverflow
Solution 1 - GroovyBob HerrmannView Answer on Stackoverflow
Solution 2 - GroovyJoshuaView Answer on Stackoverflow
Solution 3 - Groovymholm815View Answer on Stackoverflow
Solution 4 - Groovysolstice333View Answer on Stackoverflow
Solution 5 - GroovyAniket ThakurView Answer on Stackoverflow
Solution 6 - Groovyemles-kzView Answer on Stackoverflow
Solution 7 - Groovy舒何伟View Answer on Stackoverflow