Execute shell scripts from Gradle and respond to the result

Gradle is a lovely build language for those who like to customize their build scripts quite a bit. I still prefer Maven for most things but Gradle has some get up and go!

How about executing simple shell scripts from Gradle?

The following is a story from a couple years ago that has turned out to be my most popular Stack Overflow question (and answer).

You can use the Gradle exec task to execute a shell script. Using it looks like this:

task myTask(type:Exec) {

    workingDir '.'

    commandLine './myscript.sh'

}

That takes care of calling the shell script from within our Gradle script but usually we care about the result of that script. If it fails in some way, we must take a corrective action. Even if it succeeds, we probably want to know that and so we would log it or otherwise create a notification of the script’s success.

Most Gradle tasks will execute the doLast function when they are done. So you might think that adding a doLast to the exec task will take care of this for you. You’d be wrong.

task myTask(type:Exec) {

    workingDir '.'

    commandLine './myscript.sh'

    doLast {
        if(execResult == 0) {
           //one thing
        } else {
           //another thing
        }
    }
}

The above script never executes the doLast. If the shell script fails, Gradle’s built in error handling halts the entire Gradle script at that point, before the doLast block is ever reached!

Instead you see:

Execution failed for task ':project:myTask'. Process 'command './myscript.sh'' finished with non-zero exit value 1"

This leaves you in quite a pickle.

Gradle has great documentation and the documentation for exec is no different. Yet even I at first missed this. There is actually a property you can add to the exec task that allows the doLast function to execute: ignoreExitValue.

task myTask(type:Exec) {

    workingDir '.'

    commandLine './myscript.sh'

    ignoreExitValue true

    doLast {
        if(execResult == 0) {
           //one thing
        } else {
           //another thing
        }
    }
}

Somehow, figuring this out (e.g. actually reading the documentation!) has landed me hundreds of Stack Overflow points!

Leave a Reply

Your email address will not be published. Required fields are marked *