Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute a external program within a groovy script and capture the output

Tags:

groovy

I need to write a groovy script, that is executing a external program and print the output of that program to the console.

Here is the regarding code snippet:

def pmdCommand = "${scriptDir}/run.sh pmd -d ${filesToAnalyse}"

def sout = new StringBuffer()
def serr = new StringBuffer()

def process = pmdCommand.execute()
process.consumeProcessOutput(sout, serr)
process.waitFor()
if (process.exitValue() !=0 ) {
    System.err << serr.toString()
    System.exit(-1)
} 
else {
    System.out << sout.toString()
    System.exit(0)
}

I did something similar in Java, but I can't translate it to groovy.

StringBuffer output = new StringBuffer();
String s = null;

try {
    Process p = Runtime.getRuntime().exec(command);
    p.waitFor();

    BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
    BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));

    while ((s = stdInput.readLine()) != null) {
        System.out.println(s);
    }

    while ((s = stdError.readLine()) != null) {
        System.err.println(s);
    }

    System.exit(0);
}
catch (Exception e) {
    e.printStackTrace();
    System.exit(-1);
}

Update: I seems the waitFor() never returns and blocks the execution

Solution provided by Emmanuel Rosa:

def pmdCommand = "/usr/src/app/lib/pmd/bin/run.sh pmd -d ${filesToAnalyse} -f codeclimate -R ${ruleset} -l apex -v 35"

def sout = new StringBuffer()
def serr = new StringBuffer()

def process = pmdCommand.execute()
process.consumeProcessOutput(sout, serr)
process.waitForProcessOutput()

System.out << sout.toString()
System.exit(0)
like image 711
David Renz Avatar asked Oct 13 '25 11:10

David Renz


1 Answers

The documentation states that consumeProcessOutput()...

Gets the output and error streams from a process and reads them to keep the process from blocking due to a full output buffer. The processed stream data is appended to the supplied OutputStream. For this, two Threads are started, so this method will return immediately.

So far so good. Here's the important part...

The threads will not be join()ed, even if waitFor() is called.

And the solution...

To wait for the output to be fully consumed call waitForProcessOutput().

So what you can do is replace process.waitFor() with process.waitForProcessOutput().

like image 76
Emmanuel Rosa Avatar answered Oct 15 '25 13:10

Emmanuel Rosa



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!