Jenkinsfile 声明性管道 sh 命令不起作用

时间:2021-04-21 14:25:02

标签: jenkins groovy jenkins-pipeline sh

我想在 Jenkins 管道中执行这些步骤:

  1. 在构建器节点上构建 RPM(用于 CentOS)
  2. 从主节点创建一个新的 proxmox 容器(curl 以调用 PVE API)
  3. 将构建好的RPM从builder节点复制到容器节点,测试yum安装

来自终端或 bash 脚本的初始工作代码是:

// Retrieving the CT list in the VMID range 901 --> 999
VMID_LIST=$(curl --insecure --silent --cookie "$(<~/PVE_API/cookie)" -X GET https://my-proxmox:8006/api2/json/nodes/my-node/lxc | jq '.' | grep vmid | sort | cut -d'"' -f4 | grep "9[0-9][0-9]")

// Determine the first available integer
for i in $(seq 901 999)
do
    if ! echo "$VMID_LIST" | grep $i
    then
        CT_VMID=$i
        break
    fi
done

// Creating my proxmox container
curl command...

当我在某些步骤中尝试执行 sh/bash 命令时,很多时候它都失败了...

我创建了一个小管道来解释我的错误。

pipeline {
  agent { label 'master' }
  stages {
    stage("Create container") {
      steps {
        script {
          SEQ = sh(returnStdout: true, script: 'seq 1 9').trim()
          sh "echo '${SEQ}'"
          CTID = sh(returnStdout: true, script: "for id in '${SEQ}'; do echo $id; done").trim()
          sh "echo '${CTID}'"
        }
      }
    }
  }
}

如果我使用三重双引号,结果相同:

pipeline {
  agent { label 'master' }
  stages {
    stage("Create container") {
      steps {
        script {
          SEQ = sh(returnStdout: true, script: 'seq 1 9').trim()
          sh "echo '${SEQ}'"
          sh """
          for id in '{$SEQ}'
          do
            echo $id
          done
          """
        }
      }
    }
  }
}

结果:

Running in Durability level: MAX_SURVIVABILITY
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /home/jenkins/.jenkins/jobs/Services/jobs/hello_world/branches/my_branch-7.15773s/workspace
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Declarative: Checkout SCM)
[Pipeline] checkout
The recommended git tool is: git
[...snip...]
[Pipeline] }
[Pipeline] // stage
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Create container)
[Pipeline] script
[Pipeline] {
[Pipeline] sh
+ seq 1 9
[Pipeline] sh
+ echo '1
2
3
4
5
6
7
8
9'
1
2
3
4
5
6
7
8
9
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
groovy.lang.MissingPropertyException: No such property: id for class: groovy.lang.Binding
    at groovy.lang.Binding.getVariable(Binding.java:63)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:270)
    at org.kohsuke.groovy.sandbox.impl.Checker$7.call(Checker.java:353)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:357)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:333)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:333)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:333)
    at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:29)
    at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20)
    at WorkflowScript.run(WorkflowScript:9)
    at ___cps.transform___(Native Method)
    at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.get(PropertyishBlock.java:74)
    at com.cloudbees.groovy.cps.LValueBlock$GetAdapter.receive(LValueBlock.java:30)
    at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.fixName(PropertyishBlock.java:66)
    at sun.reflect.GeneratedMethodAccessor336.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
    at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
    at com.cloudbees.groovy.cps.Next.step(Next.java:83)
    at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:174)
    at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:163)
    at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:129)
    at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:268)
    at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:163)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$001(SandboxContinuable.java:18)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:51)
    at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:185)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:400)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$400(CpsThreadGroup.java:96)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:312)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:276)
    at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:67)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:139)
    at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
    at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:68)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Finished: FAILURE

如何按预期在 Jenkins 步骤中运行 sh/bash 脚本?

在 Jenkins 管道中执行所有检查或 linux 本机命令的最佳实践是什么?

为什么 Jenkins 提供了一种使用 sh/bash 命令的方法,而其中许多命令没有按预期工作?

Jenkins 专家如何做与我想做的事情类似的事情?

1 个答案:

答案 0 :(得分:0)

您需要将 $id 转义为 \$id,否则 Jenkins 会认为您正在尝试使用 Groovy var 而不是 shell var。

pipeline {
  agent { label 'master' }
  stages {
     stage("Create container") {
        steps {
        script {
           SEQ = sh(returnStdout: true, script: 'seq 1 9').trim()
           sh "echo '${SEQ}'"
           sh """
           for id in '{$SEQ}'
           do
              echo \$id
           done
           """
        }
        }
     }
  }
  }

会给你

  [Pipeline] {
  [Pipeline] stage
  [Pipeline] { (Create container)
  [Pipeline] script
  [Pipeline] {
  [Pipeline] sh
  + seq 1 9
  [Pipeline] sh
  + echo 1
  2
  3
  4
  5
  6
  7
  8
  9
  1
  2
  3
  4
  5
  6
  7
  8
  9
  [Pipeline] sh
  + echo {1 2 3 4 5 6 7 8 9}
  {1 2 3 4 5 6 7 8 9}
  [Pipeline] }
  [Pipeline] // script
  [Pipeline] }
  [Pipeline] // stage
  [Pipeline] }
  [Pipeline] // node
  [Pipeline] End of Pipeline

您可能遇到的另一个问题是 seq 在它打印的每个数字后添加一个换行符,因此您的 for 循环将无法工作,因为它需要空格分隔值而不是换行符,因此需要修复您的示例按您的预期工作。

相关问题