You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Gradle构建脚本未执行CMD中curl命令,请求排查原因

问题分析与解决:Gradle脚本未实际执行curl和tar命令

问题场景

编写了用于测试项目构建的Gradle构建脚本,预期当系统未安装指定版本(2201.6.0)的Ballerina包时,自动下载并解压该依赖包。执行脚本后控制台日志显示curl和tar命令已执行且退出值为0,但build目录中未出现下载的文件。

原build.gradle中checkBallerinaDist任务代码

task checkBallerinaDist(type: Exec) {
    def fileName = "ballerina-${ballerinaLangVersion}-swan-lake"
    def downloadLink = "https://dist.ballerina.io/downloads/${ballerinaLangVersion}/${fileName}.zip"

    workingDir project.buildDir

    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        commandLine 'cmd', '/c', 'bal', '--version'
    } else {
        commandLine 'bash', 'bal', '--version'
    }

    standardOutput = new ByteArrayOutputStream()
    ignoreExitValue = true

    doLast {
        String output = standardOutput.toString().trim()
        println "Ballerina distribution check result: $output"
        standardOutput = System.out

        if (executionResult.get().exitValue != 0 || !output.contains(ballerinaLangVersion)) {
            println "Ballerina distribution not found. Downloading..."

            if (Os.isFamily(Os.FAMILY_WINDOWS)) {
                commandLine 'cmd', '/c', 'curl', '-o', fileName + '.zip', downloadLink, '--progress-bar'
                println "Curl command executed"
                println "Command line: ${commandLine}"
                println "Working directory: ${workingDir}"
                println "Exit value: ${executionResult.get().exitValue}"
                commandLine 'cmd', '/c', 'tar', '-xf', fileName + '.zip'
                println "Tar command executed"
                println "Command line: ${commandLine}"
                println "Working directory: ${workingDir}"
                println "Exit value: ${executionResult.get().exitValue}"
            } else {
                // TODO: Handle this for Linux
            }

            System.setProperty("ballerina.home", "${project.buildDir}/${fileName}")
        } else {
            println "Ballerina distribution already exists"
            System.setProperty("ballerina.home", "${System.getenv("BALLERINA_HOME")}/distributions/ballerina-${ballerinaLangVersion}")
        }
    }
}

test {
    dependsOn checkBallerinaDist
    doFirst {
        println "Ballerina distribution path: ${System.getProperty("ballerina.home")}"
        systemProperties = [
                "target.dir"    : project.buildDir,
                "ballerina.home": System.getProperty("ballerina.home")
        ]
    }

    testLogging {
        showStackTraces = true
        showStandardStreams = true
    }

    useTestNG {
        suites "src/test/resources/testng.xml"
    }
    finalizedBy jacocoTestReport
}

执行日志

> Task :gateway-native:checkBallerinaDist
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8
Ballerina distribution check result: Ballerina 2201.5.0 (Swan Lake Update 5)
Language specification 2022R4
Update Tool 1.3.14
Ballerina distribution not found. Downloading...
Curl command executed
Command line: [cmd, /c, curl, -o, ballerina-2201.6.0-swan-lake.zip, https://dist.ballerina.io/downloads/2201.6.0/ballerina-2201.6.0-swan-lake.zip, --progress-bar]
Working directory: D:\graphql-federation-gateway\native\build
Exit value: 0
Tar command executed
Command line: [cmd, /c, tar, -xf, ballerina-2201.6.0-swan-lake.zip]
Working directory: D:\graphql-federation-gateway\native\build
Exit value: 0

> Task :gateway-native:test
Ballerina distribution path: D:\graphql-federation-gateway\native\build/ballerina-2201.6.0-swan-lake

问题根源

  1. doLast块中修改commandLine不会触发命令执行
    Exec任务的commandLine是在配置阶段就确定要执行的命令,doLast属于执行阶段的回调,此时任务的主命令(bal --version)已经执行完毕。你在doLast里修改commandLine只是改变了变量值,并没有实际调用执行这些新命令。

  2. 错误的退出值来源
    日志里打印的Exit value: 0是之前bal --version命令的退出值,不是curl或tar命令的执行结果,这导致你误以为curl和tar真的运行成功了。


修复方案

在doLast块中,不要修改commandLine,而是用Gradle提供的exec方法直接执行curl和tar命令,这样才能真正触发命令运行。修改后的checkBallerinaDist任务代码如下:

task checkBallerinaDist(type: Exec) {
    def fileName = "ballerina-${ballerinaLangVersion}-swan-lake"
    def downloadLink = "https://dist.ballerina.io/downloads/${ballerinaLangVersion}/${fileName}.zip"

    workingDir project.buildDir

    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        commandLine 'cmd', '/c', 'bal', '--version'
    } else {
        commandLine 'bash', '-c', 'bal --version' // 修正原Linux命令的错误
    }

    standardOutput = new ByteArrayOutputStream()
    ignoreExitValue = true

    doLast {
        String output = standardOutput.toString().trim()
        println "Ballerina distribution check result: $output"

        if (executionResult.get().exitValue != 0 || !output.contains(ballerinaLangVersion)) {
            println "Ballerina distribution not found. Downloading..."

            if (Os.isFamily(Os.FAMILY_WINDOWS)) {
                // 用exec方法执行curl命令
                exec {
                    commandLine 'cmd', '/c', 'curl', '-o', "${fileName}.zip", downloadLink, '--progress-bar'
                    workingDir project.buildDir
                }
                println "Curl command executed successfully"
                
                // 用exec方法执行tar命令
                exec {
                    commandLine 'cmd', '/c', 'tar', '-xf', "${fileName}.zip"
                    workingDir project.buildDir
                }
                println "Tar command executed successfully"
            } else {
                // Linux下的实现,同样用exec方法
                exec {
                    commandLine 'bash', '-c', "curl -o ${fileName}.zip ${downloadLink} --progress-bar"
                    workingDir project.buildDir
                }
                exec {
                    commandLine 'bash', '-c', "tar -xf ${fileName}.zip"
                    workingDir project.buildDir
                }
            }

            System.setProperty("ballerina.home", "${project.buildDir}/${fileName}")
        } else {
            println "Ballerina distribution already exists"
            System.setProperty("ballerina.home", "${System.getenv("BALLERINA_HOME")}/distributions/ballerina-${ballerinaLangVersion}")
        }
    }
}

补充说明

  • 用exec方法可以在执行阶段直接运行外部命令,每个exec块都会独立执行并返回自己的执行结果,若需要强制检查命令是否成功,可添加ignoreExitValue = false(默认值即为false,命令失败会抛出异常)。
  • 原Linux分支的commandLine 'bash', 'bal', '--version'存在错误,应该改为bash -c 'bal --version',否则bash会把bal当作脚本文件名执行,上述代码已一并修正。

内容的提问来源于stack exchange,提问作者Mohamed Ishad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 07:15:09