Задача Gradle exec завершается с ошибкой "execCommand == null!" - PullRequest
1 голос
/ 24 октября 2019

В моем файле build.gradle есть следующая задача:

task myTask(type:Exec) {
    def stdout = new ByteArrayOutputStream()
    exec {
        commandLine 'cmd', '/c', 'whoami'
        standardOutput = stdout;
    }
    println "Output: $stdout"
}

Когда я запускаю задачу с ./gradlew myTask, я получаю следующий вывод:

> Configure project :
Output: retrovius


> Task :myTask FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':myTask'.
> execCommand == null!

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 2s
1 actionable task: 1 executed

Задача успешно выводит мое имя пользователя (retrovius), но в любом случае не выполняется. Любые указатели на то, что я делаю неправильно?

Ответы [ 2 ]

2 голосов
/ 24 октября 2019

В зависимости от того, чего вы хотите достичь, ответ, который вы найдете, вероятно, все еще будет неправильным.

Все задачи имеют два основных этапа: конфигурирование и выполнение. Все, что вы помещаете в самый внешний блок для определения задачи, является частью конфигурации. И метод exec фактически выполняет команду всякий раз, когда оценивается этот блок кода. Поэтому, когда вы набираете:

task myTask() {
    def stdout = new ByteArrayOutputStream()
    exec {
        commandLine 'cmd', '/c', 'whoami'
        standardOutput = stdout;
    }
    println "Output: $stdout"
}

, это означает, что вы запускаете команду whoami независимо от того, какую задачу вы указываете. Если вы запустите gradle -i help, он напечатает имя. Я ожидаю, что это не то, что вы намереваетесь.

В большинстве случаев вы захотите запускать команду только тогда, когда задача действительно выполняется. Поэтому, если вы хотите, чтобы команда запускалась только при вводе gradle -i myTask, вам нужно будет вместо этого отложить ее до стадии выполнения. Это можно сделать двумя способами.

Либо вы можете поместить все в блок doLast, например, так:

task myTask() {
    doLast {
        def stdout = new ByteArrayOutputStream()
        exec {
            commandLine 'cmd', '/c', 'whoami'
            standardOutput = stdout
        }
        println "Output: $stdout"
    }
}

Или использовать тип Exec , как вы уже пробовали. Причина, по которой он не работает для вас, заключается в том, что вам нужно настроить его с помощью команды, которая вам нравится, а не запустить команду с помощью метода exec. Это может выглядеть так:

task myTask(type: Exec) {
    commandLine 'cmd', '/c', 'whoami'
    standardOutput = new ByteArrayOutputStream()
    doLast {
        println "Output: $standardOutput"
    }
}

Вы также, вероятно, избавляетесь от части cmd /c. И println следует использовать только для отладки - используйте logger.info (или .warn и т. Д.), Если вам нужно что-то вывести пользователю.

0 голосов
/ 24 октября 2019

Я понял, что единственное, что я делал неправильно, - это включил (type:Exec) в определение моей задачи. Если я помещаю следующий код в мой build.gradle файл:

task myTask() {
    def stdout = new ByteArrayOutputStream()
    exec {
        commandLine 'cmd', '/c', 'whoami'
        standardOutput = stdout;
    }
    println "Output: $stdout"
}

, я получаю следующий вывод:

> Configure project :
Output: retrovius


BUILD SUCCESSFUL in 2s

Моя ошибка, вероятно, заключалась в том, что яопределял задачу типа exec, но не давал ей команду на запуск. Это показывает фундаментальное неправильное понимание задачи exec и типа задачи с моей стороны. Если кто-то знает более конкретно, что я сделал не так, пожалуйста, не стесняйтесь комментировать и объяснять или публиковать лучший ответ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...