有没有办法通过 Jenkins 脚本控制台使用 groovy 脚本清理 Jenkins Worflowjob 工作区?
Is there any way to clean up a Jenkins Worflowjob workspace with a groovy script via Jenkins script console?
为什么又是这种类型的问题?
这个问题似乎被问过多次,但所有答案都与 Jenkins 管道作业(插件:workflow-job)无关。
情况
我正在将一堆旧的自由式作业从旧的 Jenkins 独立服务器迁移到分布式 Jenkins 环境,我决定将它们转换为 Jenkins Pipeline 作业(不能使用 Blue ocean 作为 SCM is SVN.
无论如何,对于一些工作来说,不需要清理他们的工作区,因为它们有点像 sanity/verification 工作,并且因为 SVN 检出和构建的东西的大小很大(20K 文件中的 2GB,只是删除它太慢了)。
不过我偶尔(临时)需要删除此类作业的工作区。
我不想这样做:
- 修改 Jenkins 文件并将其提交给 SVN
- "Replaying" a pipeline runs with modification
而且我没有 r/w 访问该从属节点上的 FS(这是最简单的事情)。
谷歌搜索
互联网上的快速搜索让我获得了数十个结果 [1,2, , 4, ...] 如何从 Jenkins 脚本控制台的 Groovy 脚本 运行 中清理 WS() .
不幸的是,none 尝试删除作业的真实 org.jenkinsci.plugins.workflow.job.WorkflowJob
项目实例的工作区。
我的 Groovy 尝试清理 WS
根据从互联网上收集到的答案,我启动了我的 Groovy 清理脚本,该脚本可以从 Jenkins script console <Jenkins:port/script>
中执行
import hudson.model.*
import com.cloudbees.hudson.*
import com.cloudbees.hudson.plugins.*
import com.cloudbees.hudson.plugins.folder.*
import org.jenkinsci.plugins.workflow.job.*
//jobsToRetrieve = ["aFolder/aJobInFolder","topLevelJob"]
jobsToRetrieve = ["Sandbox/PipelineTests/SamplePipeline"]
enumerateItems(Hudson.instance.items)
def enumerateItems(items) {
items.each { item ->
println("===============::: GENERAL INFO::: =======================")
println(" item: " + item)
println(" item FN: " + item.fullName)
println(" item.getClass " + item.getClass())
println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
if ( !(item instanceof Folder)) {
jobName = item.getFullDisplayName()
println(" :::jobname::: " + jobName)
if (jobsToRetrieve.contains(item.getFullName())) {
if (item instanceof WorkflowJob) {
println("XXXXXXXXXXXXX--- THIS IS THE JOB --- XXXXXXXXXXXXXXXXXXXXX")
println(" item.workspace: " + item.WORKSPACE)
println("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
println(" following methods ain't implemented for WorkflowJob type of Item\nand it will blow out.")
//see https://javadoc.jenkins.io/hudson/model/FreeStyleProject.html
println(" customWS: " + item.getCustomWorkspace())
println(" WS:" + item.getWorkspace())
item.doDoWipeOutWorkspace()
}
}
} else {
println(" :::foldername::: " + item.displayName)
enumerateItems(((Folder) item).getItems())
}
println("==========================================================")
}
}
结果(有点意料之中,但令人失望)
如您所见,我的脚本将在以下调用时爆炸:
item.getCustomWorkspace()
item.getWorkspace()
item.doDoWipeOutWorkspace()
和MissingMethodException
groovy.lang.MissingMethodException: No signature of method: org.jenkinsci.plugins.workflow.job.WorkflowJob.doDoWipeOutWorkspace() is applicable for argument types: () values: []
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:58)
at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:49)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
at Script1$_enumerateItems_closure1.doCall(Script1.groovy:33)
只是因为这些方法不适用于此类项目,但仅适用于 hudson.model.FreeStyleProject
问题:如何删除流水线作业的工作空间?
还有一个 Jenkins plugin: Workspace Cleanup 可能通过在 stage() {}
中调用 cleanWs()
在 Jenkinsfile 中使用,但我不知道如何从 Jenkinsfile 外部使用它(比如来自我的 groovy 脚本 运行 Jenkins 脚本控制台)。
它是一个bug/request用于增强 Jenkins Pipeline 作业的插件吗?
或者有没有其他方法可以将项目投射到我可以访问所需功能的地方?
这不是最漂亮的方法,但您可以执行 OS 命令:
def isWin = Jenkins.instance.windows
def cmd = isWin ? "rmdir /s /q $workspace" : "rm -rf $workspace"
cmd.execute()
如果您只使用一次代码或不处理多个 OS,您可以改为将代码缩短为相应的命令:
"rm -rf $workspace".execute()
好吧,对此进行更多调查,更多谷歌搜索并倾听您的想法(这个 one 特别受到 Daniel Spilker 的启发)我已经实现了我想要的,即:
通过 Jenkins 脚本控制台独立清理管道作业的工作空间
(只使用 Jenkins 可用的方式,不搞乱作业配置,不更新 Jenkinsfile,也不重播)
代码并不出奇的难,对于手动演示来说,它看起来像这样:
Jenkins jenkins = Jenkins.instance
Job item = jenkins.getItemByFullName('Sandbox/PipelineTests/SamplePipeline')
println("RootDir: " + item.getRootDir())
for (Node node in jenkins.nodes) {
// Make sure slave is online
if (!node.toComputer().online) {
println "Node '$node.nodeName' is currently offline - skipping workspace cleanup"
continue
}
println "Node '$node.nodeName' is online - performing cleanup:"
// Do some cleanup
FilePath wrksp = node.getWorkspaceFor(item)
println("WRKSP " + wrksp)
println("ls " + wrksp.list())
println("Free space " + wrksp.getFreeDiskSpace())
println("===== PERFORMING CLEAN UP!!! =====")
wrksp.deleteContents()
println("ls now " + wrksp.list())
println("Free space now " + wrksp.getFreeDiskSpace())
}
它的输出,如果找到你的工作,看起来像:
结果
RootDir: /var/lib/jenkins/jobs/Sandbox/jobs/PipelineTests/jobs/SamplePipeline
....
.... other node's output noise
....
Node 'mcs-ubuntu-chch' is online - performing cleanup:
WRKSP /var/lib/jenkins/workspace/Sandbox/PipelineTests/SamplePipeline
ls [/var/lib/jenkins/workspace/Sandbox/PipelineTests/SamplePipeline/README.md, /var/lib/jenkins/workspace/Sandbox/PipelineTests/SamplePipeline/.git]
Free space 3494574714880
===== PERFORMING CLEAN UP!!! =====
ls now []
Free space now 3494574919680
任务完成:)
参考资料
为什么又是这种类型的问题?
这个问题似乎被问过多次,但所有答案都与 Jenkins 管道作业(插件:workflow-job)无关。
情况
我正在将一堆旧的自由式作业从旧的 Jenkins 独立服务器迁移到分布式 Jenkins 环境,我决定将它们转换为 Jenkins Pipeline 作业(不能使用 Blue ocean 作为 SCM is SVN.
无论如何,对于一些工作来说,不需要清理他们的工作区,因为它们有点像 sanity/verification 工作,并且因为 SVN 检出和构建的东西的大小很大(20K 文件中的 2GB,只是删除它太慢了)。
不过我偶尔(临时)需要删除此类作业的工作区。 我不想这样做:
- 修改 Jenkins 文件并将其提交给 SVN
- "Replaying" a pipeline runs with modification
而且我没有 r/w 访问该从属节点上的 FS(这是最简单的事情)。
谷歌搜索
互联网上的快速搜索让我获得了数十个结果 [1,2,
不幸的是,none 尝试删除作业的真实 org.jenkinsci.plugins.workflow.job.WorkflowJob
项目实例的工作区。
我的 Groovy 尝试清理 WS
根据从互联网上收集到的答案,我启动了我的 Groovy 清理脚本,该脚本可以从 Jenkins script console <Jenkins:port/script>
import hudson.model.*
import com.cloudbees.hudson.*
import com.cloudbees.hudson.plugins.*
import com.cloudbees.hudson.plugins.folder.*
import org.jenkinsci.plugins.workflow.job.*
//jobsToRetrieve = ["aFolder/aJobInFolder","topLevelJob"]
jobsToRetrieve = ["Sandbox/PipelineTests/SamplePipeline"]
enumerateItems(Hudson.instance.items)
def enumerateItems(items) {
items.each { item ->
println("===============::: GENERAL INFO::: =======================")
println(" item: " + item)
println(" item FN: " + item.fullName)
println(" item.getClass " + item.getClass())
println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
if ( !(item instanceof Folder)) {
jobName = item.getFullDisplayName()
println(" :::jobname::: " + jobName)
if (jobsToRetrieve.contains(item.getFullName())) {
if (item instanceof WorkflowJob) {
println("XXXXXXXXXXXXX--- THIS IS THE JOB --- XXXXXXXXXXXXXXXXXXXXX")
println(" item.workspace: " + item.WORKSPACE)
println("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
println(" following methods ain't implemented for WorkflowJob type of Item\nand it will blow out.")
//see https://javadoc.jenkins.io/hudson/model/FreeStyleProject.html
println(" customWS: " + item.getCustomWorkspace())
println(" WS:" + item.getWorkspace())
item.doDoWipeOutWorkspace()
}
}
} else {
println(" :::foldername::: " + item.displayName)
enumerateItems(((Folder) item).getItems())
}
println("==========================================================")
}
}
结果(有点意料之中,但令人失望)
如您所见,我的脚本将在以下调用时爆炸:
item.getCustomWorkspace()
item.getWorkspace()
item.doDoWipeOutWorkspace()
和MissingMethodException
groovy.lang.MissingMethodException: No signature of method: org.jenkinsci.plugins.workflow.job.WorkflowJob.doDoWipeOutWorkspace() is applicable for argument types: () values: []
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:58)
at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:49)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
at Script1$_enumerateItems_closure1.doCall(Script1.groovy:33)
只是因为这些方法不适用于此类项目,但仅适用于 hudson.model.FreeStyleProject
问题:如何删除流水线作业的工作空间?
还有一个 Jenkins plugin: Workspace Cleanup 可能通过在 stage() {}
中调用 cleanWs()
在 Jenkinsfile 中使用,但我不知道如何从 Jenkinsfile 外部使用它(比如来自我的 groovy 脚本 运行 Jenkins 脚本控制台)。
它是一个bug/request用于增强 Jenkins Pipeline 作业的插件吗? 或者有没有其他方法可以将项目投射到我可以访问所需功能的地方?
这不是最漂亮的方法,但您可以执行 OS 命令:
def isWin = Jenkins.instance.windows
def cmd = isWin ? "rmdir /s /q $workspace" : "rm -rf $workspace"
cmd.execute()
如果您只使用一次代码或不处理多个 OS,您可以改为将代码缩短为相应的命令:
"rm -rf $workspace".execute()
好吧,对此进行更多调查,更多谷歌搜索并倾听您的想法(这个 one 特别受到 Daniel Spilker 的启发)我已经实现了我想要的,即:
通过 Jenkins 脚本控制台独立清理管道作业的工作空间
(只使用 Jenkins 可用的方式,不搞乱作业配置,不更新 Jenkinsfile,也不重播)
代码并不出奇的难,对于手动演示来说,它看起来像这样:
Jenkins jenkins = Jenkins.instance
Job item = jenkins.getItemByFullName('Sandbox/PipelineTests/SamplePipeline')
println("RootDir: " + item.getRootDir())
for (Node node in jenkins.nodes) {
// Make sure slave is online
if (!node.toComputer().online) {
println "Node '$node.nodeName' is currently offline - skipping workspace cleanup"
continue
}
println "Node '$node.nodeName' is online - performing cleanup:"
// Do some cleanup
FilePath wrksp = node.getWorkspaceFor(item)
println("WRKSP " + wrksp)
println("ls " + wrksp.list())
println("Free space " + wrksp.getFreeDiskSpace())
println("===== PERFORMING CLEAN UP!!! =====")
wrksp.deleteContents()
println("ls now " + wrksp.list())
println("Free space now " + wrksp.getFreeDiskSpace())
}
它的输出,如果找到你的工作,看起来像:
结果
RootDir: /var/lib/jenkins/jobs/Sandbox/jobs/PipelineTests/jobs/SamplePipeline
....
.... other node's output noise
....
Node 'mcs-ubuntu-chch' is online - performing cleanup:
WRKSP /var/lib/jenkins/workspace/Sandbox/PipelineTests/SamplePipeline
ls [/var/lib/jenkins/workspace/Sandbox/PipelineTests/SamplePipeline/README.md, /var/lib/jenkins/workspace/Sandbox/PipelineTests/SamplePipeline/.git]
Free space 3494574714880
===== PERFORMING CLEAN UP!!! =====
ls now []
Free space now 3494574919680
任务完成:)