繁体   English   中英

"无法在 Jenkins 的 Groovy 中运行 shell 命令"

[英]Unable to run shell command in Groovy in Jenkins

我试图通过运行 shell 命令从从站获取某些值,例如:

git rev-parse HEAD
git config --get remote.origin.url

我为此尝试编写的方法是:

def executeCommand(String command) {
    stdout = sh script: command, returnStdout: true
    return stdout.trim()
}

现在,当我尝试运行第一个命令时:

output = executeCommand('git rev-parse HEAD')

我得到错误:

[Running] groovy "/Users/user-a/Documents/cmd.groovy"
Caught: groovy.lang.MissingMethodException: No signature of method: cmd.sh() is applicable for argument types: (LinkedHashMap) values: [[script:git rev-parse HEAD, returnStdout:true]]
Possible solutions: is(java.lang.Object), use([Ljava.lang.Object;), run(), run(), any(), tap(groovy.lang.Closure)
groovy.lang.MissingMethodException: No signature of method: cmd.sh() is applicable for argument types: (LinkedHashMap) values: [[script:git rev-parse HEAD, returnStdout:true]]
Possible solutions: is(java.lang.Object), use([Ljava.lang.Object;), run(), run(), any(), tap(groovy.lang.Closure)
    at cmd.executeCommand(cmd.groovy:2)
    at cmd.run(cmd.groovy:6)

我也试过:

output = command.execute().text

但这没有任何回报。

我没有关于如何在 Jenkins 中的 Groovy 中运行 shell 命令并记录输出的想法。

更多细节

我正在使用 Jenkins 共享库。 我已经为我的Jenkinsfile公开了一个名为getLatestBuildDetails()的方法。 这个方法是在我的库中定义的。 该方法中的一项操作是在本地执行git命令。 因此,为了在本地运行任何 shell 命令,我创建了executeCommand函数,该函数将实际命令作为字符串运行并执行它并返回输出以供getLatestBuildDetails()稍后使用

库类不能直接调用sh或git等步骤 但是,它们可以在封闭类的范围之外实现方法,而后者又调用Pipeline步骤,例如:

// src/org/foo/Zot.groovy
package org.foo;

def checkOutFrom(repo) {
  git url: "git@github.com:jenkinsci/${repo}"
}

return this

然后可以从脚本管道中调用它:

def z = new org.foo.Zot()
z.checkOutFrom(repo)

这种方法有局限性; 例如,它阻止了超类的声明。

或者,可以使用此方法将一组步骤显式传递给库类,构造函数或只有一个方法:

package org.foo
class Utilities implements Serializable {
  def steps
  Utilities(steps) {this.steps = steps}
  def mvn(args) {
    steps.sh "${steps.tool 'Maven'}/bin/mvn -o ${args}"
  }
}

在类(例如上面)上保存状态时,该类必须实现Serializable接口。 这确保了使用该类的Pipeline(如下例所示)可以在Jenkins中正确挂起和恢复。

@Library('utils') import org.foo.Utilities
def utils = new Utilities(this)
node {
  utils.mvn 'clean package'
}

如果库需要访问全局变量(例如env),则应以类似的方式将这些变量显式传递到库类或方法中。

而不是将多个变量从Scripted Pipeline传递到库中,

package org.foo
class Utilities {
  static def mvn(script, args) {
    script.sh "${script.tool 'Maven'}/bin/mvn -s ${script.env.HOME}/jenkins.xml -o ${args}"
  }
}

上面的示例显示了脚本被传递给一个静态方法,从Scripted Pipeline调用,如下所示:

@Library('utils') import static org.foo.Utilities.*
node {
  mvn this, 'clean package'
}

在你的情况下,你应该写如下:

def getLatestBuildDetails(context){
    //...
    executeCommand(context, 'git rev-parse HEAD')
    //...
}

def executeCommand(context, String command) {
    stdout = script.sh(script: command, returnStdout: true)
    return stdout.trim()
}

詹金斯档案:

@Library('library_name') _
getLatestBuildDetails(this)

有关更多信息,请参阅jenkins共享库文档: https ://jenkins.io/doc/book/pipeline/shared-libraries/

我也在使用共享库。 这就是我在代码中使用的方式:

String getMavenProjectName() {
    echo "inside getMavenProjectName +++++++"
    // mavenChartName = sh(
    //         script: "git config --get remote.origin.url",
    //         returnStdout: true
    // ).trim()
    def mavenChartName = sh returnStdout:true, script: '''
    #!/bin/bash
    GIT_LOG=$(env -i git config --get remote.origin.url)
    basename "$GIT_LOG" .git; '''
    echo "mavenChartName: ${mavenChartName}"
    return mavenChartName
}

尝试sh步而不是执行。 :)

编辑:我会使用execute()或者我认为它更好, grgit 我认为你运行cmd.execute().text时没有得到任何输出,因为.text返回命令的标准输出,你的命令可能只使用标准错误作为输出,你可以检查两个:

def process = cmd.execute()
def stdOut = process.inputStream.text
def stdErr = process.errorStream.text

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM