Is there a way to stream the output of a long Groovy execute() command to the console rather than wait for it to finish?

Viewed 3729

I'm running a shell command via a system Groovy script. It's a long running process, about 30 minutes, and it is quite verbose. But as written, this waits for the command to complete before printing stdout or stderr. Is there a way to have the output go to the console as the script executes (like it would in a terminal session).

def sout = new StringBuffer(), serr = new StringBuffer()
def proc = "/some/long/running/command".execute()

proc.consumeProcessOutput(sout, serr)
println "STDOUT\n $sout"
println "STDERR\n $serr"

Update: This is the code I'm trying based on the answer. It doesn't print anything until after the process completes, or is killed.

def cmd = "/home/adam/test.sh"
StringBuffer sout = new StringBuffer()
StringBuffer serr = new StringBuffer()
def process = cmd.execute()
process.waitForProcessOutput sout, serr
sout.each 
   println "Line ${it}"
}
4 Answers

While the solution you found will probably work fine, I think it is better to use waitForProcessOutput which also allows to stream the error output of the process.

The full solution would be something like this:

#!/usr/bin/env groovy
Process proc = "ping -c 10 google.com".execute()
proc.waitForProcessOutput(System.out, System.err)
System.exit(proc.exitValue())

There are several alternatives to this method to capture only normal output or only error output for example. You can find them here.

There is also a (rather short) chapter on executing external processes on the Groovy docs.

This was the solution I found.

proc.in.eachLine { line -> println line }
proc.out.close()
proc.waitFor()

After a long search, I was not able to get the exact solution. This worked for me:

public int Execute(def command, File dir) {
          println("command: ${command}")
          Process process = command.execute(null, dir)
          def out = new StringBuffer()
          def err = new StringBuffer()
          process.consumeProcessOutput(out, err)
          while(1) {
              err.eachLine {line, count ->
                  println("${line}")
                  err.setLength(0)
              }
              out.eachLine { line, count ->
                  println("${line}")
                  out.setLength(0)
              }
              if(! process.isAlive()) {
                  break
                  }
              }
         return process.exitValue()
         }

The below script works :


    def pmdCommand = "java -cp D:\\Users\\user1\\work\\backup\\work\\LOG-SHELL-FIX\\EAR\\Encrypter.jar com.mdm.custom.main.Encrypter password123 ${publicKey}"
    def sout = new StringBuffer()
    def serr = new StringBuffer()

    Process process = pmdCommand.execute()
    process.waitForProcessOutput(sout,serr) // This is a better way to read the output
    if(sout.size()>0) log.info "$sout"
    if(serr.size()>0) log.info "$serr"

The Groovy method reference is available at : http://docs.groovy-lang.org/docs/groovy-latest/html/api/org/codehaus/groovy/runtime/ProcessGroovyMethods.html

Related