55

我正在尝试实现一个 gradle 任务,从一系列环境变量值和 shell 执行中动态创建一个 buildsignature.properties 文件。我大部分时间都在工作,但我似乎无法获得 shell 命令的输出。这是我的任务...

task generateBuildSignature << {
    ext.whoami = exec() {
        executable = "whoami"
    }
    ext.hostname = exec() {
         executable = "hostname"
    }
    ext.buildTag = System.env.BUILD_TAG ?: "dev"

    ant.propertyfile(
        file: "${buildDir}/buildsignature.properties",
        comment: "This file is automatically generated - DO NOT EDIT!" ) {
        entry( key: "version", value: "${project.version}" )
        entry( key: "buildTimestamp", value: "${new Date().format('yyyy-MM-dd HH:mm:ss z')}" )
        entry( key: "buildUser", value: "${ext.whoami}" )
        entry( key: "buildSystem", value: "${ext.hostname}" )
        entry( key: "buildTag", value: "$ext.buildTag" )
    }
}

但是生成的属性字段没有得到 buildUser 和 buildSystem 的预期结果。

#This file is automatically generated - DO NOT EDIT!
#Mon, 18 Jun 2012 18:14:14 -0700
version=1.1.0
buildTimestamp=2012-06-18 18\:14\:14 PDT
buildUser=org.gradle.process.internal.DefaultExecHandle$ExecResultImpl@2e6a54f9
buildSystem=org.gradle.process.internal.DefaultExecHandle$ExecResultImpl@46f0bf3d
buildTag=dev

如何让 buildUser 和 buildSystem 匹配相应 exec 的输出,而不是一些默认的 ExecResultImpl toString?这真的不会那么难,不是吗?

4

6 回答 6

73

这是我从 exec 获取标准输出的首选语法:

def stdout = new ByteArrayOutputStream()
exec{
    commandLine "whoami"
    standardOutput = stdout;
}
println "Output:\n$stdout";

在这里找到:http: //gradle.1045684.n5.nabble.com/external-process-execution-td1431883.html (请注意,页面有一个错字,但提到了 ByteArrayInputStream 而不是 ByteArrayOutputStream)

于 2012-12-01T16:42:03.477 回答
60

这篇文章描述了如何解析Exec调用的输出。您将在下面找到两个运行您的命令的任务。

task setWhoamiProperty {
    doLast {
        new ByteArrayOutputStream().withStream { os ->
            def result = exec {
                executable = 'whoami'
                standardOutput = os
            }
            ext.whoami = os.toString()
        }
    }
}

task setHostnameProperty {
    doLast {
        new ByteArrayOutputStream().withStream { os ->
            def result = exec {
                executable = 'hostname'
                standardOutput = os
            }
            ext.hostname = os.toString()
        }
    }
}

task printBuildInfo {
    dependsOn setWhoamiProperty, setHostnameProperty
    doLast {
         println whoami
         println hostname
    }
}

实际上有一种更简单的方法来获取这些信息,而无需调用 shell 命令。

当前登录用户:System.getProperty('user.name')

主机名:InetAddress.getLocalHost().getHostName()

于 2012-06-19T02:53:42.557 回答
14

使用kotlin-dsl

import java.io.ByteArrayOutputStream

val outputText: String = ByteArrayOutputStream().use { outputStream ->
  project.exec {
    commandLine("whoami")
    standardOutput = outputStream
  }
  outputStream.toString()
}
于 2018-09-17T13:04:02.470 回答
8

在许多情况下,Groovy 允许更简单的实现。因此,如果您使用基于 Groovy 的构建脚本,您可以简单地执行以下操作:

def cmdOutput = "command line".execute().text
于 2020-09-26T19:49:09.603 回答
6

Exec 的 Gradle 文档中解释

task execSomething {
  doFirst {
    exec {
      workingDir '/some/dir'
      commandLine '/some/command', 'arg'

      ...
      //store the output instead of printing to the console:
      standardOutput = new ByteArrayOutputStream()

      //extension method execSomething.output() can be used to obtain the output:
      ext.output = {
        return standardOutput.toString()
      }
    }
  }
}
于 2017-12-01T03:02:50.590 回答
1

kotlin-dsl 变体

Groovy 风格

buildSrc中:

import org.codehaus.groovy.runtime.ProcessGroovyMethods

fun String.execute(): Process = ProcessGroovyMethods.execute(this)
fun Process.text(): String = ProcessGroovyMethods.getText(this)

build.gradle.kts:

"any command you want".execute().text().trim()

执行风格

buildSrc中:

import org.gradle.api.Project
import org.gradle.process.ExecSpec
import java.io.ByteArrayOutputStream

fun Project.execWithOutput(spec: ExecSpec.() -> Unit) = ByteArrayOutputStream().use { outputStream ->
    exec {
        this.spec()
        this.standardOutput = outputStream
    }
    outputStream.toString().trim()
}

build.gradle.kts:

val outputText = project.execWithOutput {
    commandLine("whoami")
}

//variable project is actually optional

val outputText = execWithOutput {
    commandLine("whoami")
}
于 2021-12-11T16:54:03.563 回答