Jenkins管道:运行shell命令返回"错误替换",但为什么?

时间:2017-06-14 10:55:58

标签: jenkins groovy jenkins-pipeline

我想填充常规变量" committer"使用命令的输出:

def committer = utils.sh("curl -s -u \${J_USER}:\${J_PASS} \${env.BUILD_URL}/api/json | python -mjson.tool | grep authorEmail | awk '{print \$2}' | tr -d '"|,' ")

由于Jenkins (JENKINS-26133)中存在已知问题,因此无法执行此操作,只能使用命令的退出状态填充变量。

所以我已经完成了这两项功能:

def gen_uuid(){
    randomUUID() as String
}

def sh_out(cmd){ // As required by bug JENKINS-26133
    String uuid = gen_uuid()
    sh """( ${cmd} )> ${uuid}"""
    String out = readFile(uuid).trim()
    sh "set +x ; rm ${uuid}"
    return out
}

这些函数允许我使用上面提到的known issue link中建议的解决方法将我的shell命令包装在sh_out(COMMAND)和后台中,这意味着在重定向时运行命令& #39;输出到文件(在我的函数的情况下,它是随机文件名),然后将其读入变量。

所以,在我的管道的开头,我加载了我的函数文件,结尾为return this;,如下所示:

fileLoader.withGit('git@bitbucket.org:company/pipeline_utils.git', 'master', git_creds, ''){
    utils = fileLoader.load('functions.groovy');
}

这就是" utils.sh_out"你在命令中看到,但是当我在Jenkins管道中使用上面显示的命令时,我收到以下错误:

/home/ubuntu/workspace/-6870-bitbucket-integration-ECOPKSSBUJ6HCDNM4TOY77X7UTZ@tmp/durable-006d5c7e/script.sh: 2: /home/ubuntu/workspace/-6870-bitbucket-integration-ECOPKSSBUJ6HCDNM4TOY77X7UTZ@tmp/durable-006d5c7e/script.sh: Bad substitution

在shell中运行命令可以正常工作:

$ curl -s -u user:password http://IPADDR:8080/job/COMPANY_BitBucket_Integration/job/research/job/COMPANY-6870-bitbucket-integration/3/api/json/api/json | python -mjson.tool | grep authorEmail | awk '{print $2}' | tr -d '"|,'
user@email.com

我怀疑它最终与tr命令有关,而且我在那里逃避了角色,但无论我尝试失败,有人都有了想法吗?

1 个答案:

答案 0 :(得分:1)

根据documentation现在sh支持标准输出。

我知道我没有直接回答你的问题,但我建议使用groovy来解析json。

您正试图从json

获取authorEmail的值

如果来自/api/json的回复看起来像这样(只是一个例子):

{
  "a":{
    "b":{
      "c":"ccc",
      "authorEmail":"user@email.com"
    }
  }
}

然后groovy采取athorEmail

def cmd = "curl -s -u \${J_USER}:\${J_PASS} \${env.BUILD_URL}/api/json"
def json = sh(returnStdout: true, script: cmd).trim()
//parse json and access it as an object (Map/Array)
json = new groovy.json.JsonSlurper().parseText(json)
def mail = json.a.b.athorEmail

您可以收到java.io.NotSerializableException explained here

所以我改变了这样的代码:

node {
    def json = sh(
            returnStdout: true, 
            script: "curl -s -u \${J_USER}:\${J_PASS} \${env.BUILD_URL}/api/json"
        ).trim()
    def mail = evaluateJson(json, '${json.a.b.authorEmail}')
    echo mail
}

@NonCPS
def evaluateJson(String json, String gpath){
    //parse json
    def ojson = new groovy.json.JsonSlurper().parseText(json)
    //evaluate gpath as a gstring template where $json is a parsed json parameter
    return new groovy.text.GStringTemplateEngine().createTemplate(gpath).make(json:ojson).toString()
}