Unclear semantics of commandLine argument on Exec task

I am, for the first time, trying to use the Exec task and the results are strange to say the least:

Caused by: java.io.IOException: Cannot run program "sum -s /home/sc1478/civr/content/build/distributions/civr-9.1.3-cas.noarch.rpm" (in directory "/"): error=2, No such file or directory
        at net.rubygrapefruit.platform.internal.DefaultProcessLauncher.start(DefaultProcessLauncher.java:25)
        ... 4 more
Caused by: java.io.IOException: error=2, No such file or directory
        ... 5 more


BUILD FAILED

Total time: 2.83 secs
~/civr (master *)$ sum -s /home/sc1478/civr/content/build/distributions/civr-9.1.3-cas.noarch.rpm
22419 14421 /home/sc1478/civr/content/build/distributions/civr-9.1.3-cas.noarch.rpm

I literally copied the command which the stacktrace just reported as having failed, to the command-line and ran it manually, and the command worked from there. How could that be?

Here is the code of the Exec task:

        sumTask = project.tasks.create("sum", Exec) {
            //store the output instead of printing to the console:
            standardOutput = new ByteArrayOutputStream()

            ext.output = {
                return standardOutput.toString()
            }
            workingDir '/'  // also tried without this, from project directory, with same result
                                // should not matter since path is absolute
                                    
            project.afterEvaluate {
            // have to do this afterEvaluate since the name of the output file 
            // is not known at configuration time
                project.tasks.withType(Rpm.class) { Task t ->
                    commandLine "sum -s ${t.outputs.files.singleFile}"
                }
            }
        }

What am I missing?

And doing it this way, that is figuring the working dir afterEvaluate, fails for the same reason:

            sumTask = project.tasks.create("sum", Exec) {
                //store the output instead of printing to the console:
                standardOutput = new ByteArrayOutputStream()
    
                //extension method output() can be used to obtain the output:
                ext.output = {
                    return standardOutput.toString()
                }

                project.afterEvaluate {
                    project.tasks.withType(Rpm.class) { Task t ->
                        def path = t.outputs.files.singleFile.parent
                        def name = t.outputs.files.singleFile.name
                        workingDir path
                        commandLine "sum -s ${name}"
                    }
                }
            }

Error:

Caused by: java.io.IOException: Cannot run program "sum -s civr-9.1.3-cas.noarch.rpm" (in directory "/home/sc1478/civr/content/build/distributions"): error=2, No such file or directory
        at net.rubygrapefruit.platform.internal.DefaultProcessLauncher.start(DefaultProcessLauncher.java:25)
        ... 4 more
Caused by: java.io.IOException: error=2, No such file or directory
        ... 5 more


BUILD FAILED

Total time: 3.24 secs
~/civr (master *)$ ls -al /home/sc1478/civr/content/build/distributions
total 7220
drwxr-x--- 2 sc1478 dev    4096 Aug 20 08:19 .
drwxr-x--- 9 sc1478 dev    4096 Aug 20 08:19 ..
-rw-r----- 1 sc1478 dev 7383231 Aug 20 08:19 civr-9.1.3-cas.noarch.rpm

Could you try changing the “sum” reference in the command line to be the fully-qualified path to the “sum” executable?

Thanks, but changing it to

commandLine "/usr/bin/sum -s ${name}"

made no difference.

The problem seems to be with the “command” executable that the exec task is doing.
I didn’t look at enough of the stack trace:

Caused by: org.gradle.process.internal.ExecException: A problem occurred starting process 'command '/usr/bin/sum -s civr-9.1.3-cas.noarch.rpm''
        at org.gradle.process.internal.DefaultExecHandle.setEndStateInfo(DefaultExecHandle.java:198)
        at org.gradle.process.internal.DefaultExecHandle.failed(DefaultExecHandle.java:329)
        at org.gradle.process.internal.ExecHandleRunner.run(ExecHandleRunner.java:86)
        ... 2 more
Caused by: net.rubygrapefruit.platform.NativeException: Could not start '/usr/bin/sum -s civr-9.1.3-cas.noarch.rpm'
        at net.rubygrapefruit.platform.internal.DefaultProcessLauncher.start(DefaultProcessLauncher.java:27)
        at net.rubygrapefruit.platform.internal.WrapperProcessLauncher.start(WrapperProcessLauncher.java:36)
        at org.gradle.process.internal.ExecHandleRunner.run(ExecHandleRunner.java:68)
        ... 2 more
Caused by: java.io.IOException: Cannot run program "/usr/bin/sum -s civr-9.1.3-cas.noarch.rpm" (in directory "/home/sc1478/civr/content/build/distributions"): error=2, No such file or directory
        at net.rubygrapefruit.platform.internal.DefaultProcessLauncher.start(DefaultProcessLauncher.java:25)
        ... 4 more
Caused by: java.io.IOException: error=2, No such file or directory
        ... 5 more

This, I can reproduce from the command line:

~/civr (master *)$ cd /home/sc1478/civr/content/build/distributions
~/civr/content/build/distributions (master *)$ command 'sum -s civr-9.1.3-cas.noarch.rpm'
-bash: sum -s civr-9.1.3-cas.noarch.rpm: command not found

Can this be turned off?

You need to separate each argument instead of passing a single String. You are literally trying to call a program named “sum -s /someFile”.

Instead do

commandLine "sum", "-s", t.outputs.files.singleFile.path

Thanks, Stefan, that works and your explanation does explain clearly what first looked mysterious to me. Although the documentation does recommend passing a list of args, it doesn’t say what happens if you do it the other way. I originally started doing it as the documentation recommends. It failed for other reasons, which I solved, but I never tried going back to the list of args.It would be helpful if the docs were a little more specific about this.