jenkins - Jenkinsfile 声明性管道 sh 命令不起作用
问题描述
我想在 Jenkins 管道中执行这些步骤:
- 在构建器节点上构建 RPM(用于 CentOS)
- 从主节点创建一个新的 proxmox 容器(curl 调用 PVE API)
- 将构建的 RPM 从 builder 节点复制到容器节点以测试 yum install
- 等等
来自终端或 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 专家如何做与我想做的事情相似的事情?
解决方案
您将需要逃避$id
,\$id
否则 Jenkins 会认为您正在尝试使用 Groovy var 而不是 shell var。
IE
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 循环将无法工作,因为它需要空格分隔的值而不是换行符,因此需要修复您的示例才能按预期工作。
推荐阅读
- php - 如何在 couchbase 中创建没有密码的用户?
- reactjs - 在反应中迭代对象内的对象
- linux-kernel - 如何在火焰图中包含指定的函数?
- sql - 如何通过 Automic 将 SQL 脚本结果作为电子邮件正文中的表格发送
- jira - 没有可用的“com.atlassian.velocity.VelocityManager”类型的合格 bean
- sql - Postgres内部json更新
- javascript - 无法让 onChange 函数在使用网格容器的 React 上工作
- javascript - Angular - HTTPClientModule 删除请求不起作用
- java - Apache poi:使用 apache poi 在工作表级别设置自定义属性
- java - Spring 5,基本身份验证和base64密码编码器