我們有八個節點哈德森集羣。當一個特定的代碼分支不再積極利用,我們禁用的構建工作,但該作業的工作空間仍然流連佔用空間中的所有節點上。如何觸發哈德森的人工清理工作區
我正在尋找一種方式來觸發在所有節點的工作空間的清理。請注意,我沒有在「構建之前」找到「乾淨的工作區」解決方案。
我們有八個節點哈德森集羣。當一個特定的代碼分支不再積極利用,我們禁用的構建工作,但該作業的工作空間仍然流連佔用空間中的所有節點上。如何觸發哈德森的人工清理工作區
我正在尋找一種方式來觸發在所有節點的工作空間的清理。請注意,我沒有在「構建之前」找到「乾淨的工作區」解決方案。
這聽起來像你「禁用時所建刪除工作區」的解決方案尋找。你可以寫一個哈德森插件來做到這一點。這可能是過度殺傷。
如果我不得不這樣做(這我不會因爲我們沒有磁盤空間不足),我會寫一個腳本單位找哈德森目錄下的所有殘疾人的就業機會。作業由XML文件表示。然後,我會讓腳本刪除任何匹配的工作區。我可能會在cron中設置它,所以它每晚或每週運行一次,或者在環境中適當運行。
你並不需要編寫一個插件。您可以編寫一個利用Groovy plugin編寫Groovy系統腳本的作業。這項工作每晚都會運行。它會識別殘疾項目並刪除其工作區。這裏是您的腳本可以使用的Hudson Model API的鏈接。在http://<hudson-server>/script
有一個Groovy腳本控制檯,對調試非常有用。
這是一段代碼片段,應該對你有直接的好處。在腳本控制檯運行它,並檢查輸出:
def hi = hudson.model.Hudson.instance
hi.getItems(hudson.model.Job).each {
job ->
println(job.displayName)
println(job.isDisabled())
println(job.workspace)
}
您也可以找到代碼片段this answer有用。他們提到Jenkins API,但在這個層面上,我認爲Jenkins和Hudson之間沒有區別。
更新:
這裏是你如何能做到這在多個從站:創建一個對所有從動運行多配置工作(也稱爲「矩陣工作」)。在每個從以下系統Groovy腳本會給你每一項工作的工作區對從(以及啓用/禁用標誌):
def hi = hudson.model.Hudson.instance
def thr = Thread.currentThread()
def build = thr?.executable
def node = build.executor.owner.node
hi.getItems(hudson.model.Job).each {
job ->
println("---------")
println(job.displayName)
println(job.isDisabled())
println(node.getWorkspaceFor(job))
}
在腳本上的從本身可以消滅運行直接從它的工作區。當然,崇拜空間可能不存在,但這不是問題。請注意,您只需編寫腳本一次--Jenkins將自動在矩陣作業中指定的所有從站上運行它。
那麼,我將使用哪個API來操作各種構建節點上的工作區。迭代工作並檢查他們的狀態很簡單,但並沒有讓我走得很遠。我需要一個循環遍歷所有節點的內部循環,以某種方式檢查該節點是否實際上具有該作業的工作區,以及是否以某種方式刪除它。最後一部分可能是最具挑戰性的,除非Hudson已經有API在給定節點上刪除Job的工作區。 – 2012-07-09 19:33:23
看起來您需要迭代節點並使用[hudson.model.Node.getWorkspaceFor()]獲取每個節點的每個作業的工作空間(http://www.jarvana.com/jarvana/view/org/jvnet/hudson/ main/hudson-core/1.313/hudson-core-1.313-javadoc.jar!/hudson/model/Node.html#getWorkspaceFor(hudson.model.TopLevelItem))方法。我有一個想法,在這種情況下可以完成擦除操作(使用在所有節點上運行的多配置構建),但是我需要檢查明天是否可以實施(以及如何)。做zavtra。 – 2012-07-09 22:22:30
我曾嘗試下面的腳本,它適用於單個節點,
def hi = hudson.model.Hudson.instance
hi.getItems(hudson.model.Job).each {
job ->
if(job.isDisabled())
{
println(job.displayName)
job.doDoWipeOutWorkspace()
}
}
以下Groovy腳本溼巾所有節點上的某些工作的工作空間。從「Jenkins host」/ computer /(master)/ script執行它
在TODO部分中,將作業名稱更改爲所需的名稱。
import hudson.model.*
// For each job
for (item in Hudson.instance.items)
{
jobName = item.getFullDisplayName()
// check that job is not building
if (!item.isBuilding())
{
// TODO: Modify the following condition to select which jobs to affect
if (jobName == "MyJob")
{
println("Wiping out workspaces of job " + jobName)
customWorkspace = item.getCustomWorkspace()
println("Custom workspace = " + customWorkspace)
for (node in Hudson.getInstance().getNodes())
{
println(" Node: " + node.getDisplayName())
workspacePath = node.getWorkspaceFor(item)
if (workspacePath == null)
{
println(" Could not get workspace path")
}
else
{
if (customWorkspace != null)
{
workspacePath = node.getRootPath().child(customWorkspace)
}
pathAsString = workspacePath.getRemote()
if (workspacePath.exists())
{
workspacePath.deleteRecursive()
println(" Deleted from location " + pathAsString)
}
else
{
println(" Nothing to delete at " + pathAsString)
}
}
}
}
}
else
{
println("Skipping job " + jobName + ", currently building")
}
}
它有點晚,但我遇到了同樣的問題。我的腳本會檢查是否有至少2GB的空間可用。如果不是這種情況,則節點上的所有工作區都被清除以釋放空間。
import hudson.FilePath.FileCallable
import hudson.slaves.OfflineCause
for (node in Jenkins.instance.nodes) {
computer = node.toComputer()
if (computer.getChannel() == null) continue
rootPath = node.getRootPath()
size = rootPath.asCallableWith({f, c -> f.getUsableSpace()} as FileCallable).call()
roundedSize = size/(1024 * 1024 * 1024) as int
println("node: " + node.getDisplayName() + ", free space: " + roundedSize + "GB")
if (roundedSize < 2) {
computer.setTemporarilyOffline(true, [toString: {"disk cleanup"}] as OfflineCause)
for (item in Jenkins.instance.items) {
jobName = item.getFullDisplayName()
if (item.isBuilding()) {
println(".. job " + jobName + " is currently running, skipped")
continue
}
println(".. wiping out workspaces of job " + jobName)
workspacePath = node.getWorkspaceFor(item)
if (workspacePath == null) {
println(".... could not get workspace path")
continue
}
println(".... workspace = " + workspacePath)
customWorkspace = item.getCustomWorkspace()
if (customWorkspace != null) {
workspacePath = node.getRootPath().child(customWorkspace)
println(".... custom workspace = " + workspacePath)
}
pathAsString = workspacePath.getRemote()
if (workspacePath.exists()) {
workspacePath.deleteRecursive()
println(".... deleted from location " + pathAsString)
} else {
println(".... nothing to delete at " + pathAsString)
}
}
computer.setTemporarilyOffline(false, null)
}
}
「size = rootPath.asCallableWith({f,c - > f.getUsableSpace()} as FileCallable).call()」對我崩潰:java.io.IOException:無法序列化[email protected] – 2014-01-11 15:12:23
我嘗試修復:https://gist.github.com/rb2k/8372402 – 2014-01-11 15:42:42
我最近也在尋找清理我的詹金斯的工作空間,但有一點扭曲:我想僅從不再存在就業刪除工作區。這是因爲jenkins在刪除工作時並沒有擺脫工作空間,這非常煩人。 而我們現在只使用一個主人,沒有單獨的節點。
我發現了一個腳本的地方(找不到了鏈接),但調整了它一下我們的使用,把它在一個詹金斯工作與「執行系統Groovy腳本」生成步驟,每天運行:
import hudson.FilePath
import jenkins.model.Jenkins
import hudson.model.Job
def deleteUnusedWorkspace(FilePath root, String path) {
root.list().sort{child->child.name}.each { child ->
String fullName = path + child.name
def item = Jenkins.instance.getItemByFullName(fullName);
println "Checking '$fullName'"
try{
if (item.class.canonicalName == 'com.cloudbees.hudson.plugins.folder.Folder') {
println "-> going deeper into the folder"
deleteUnusedWorkspace(root.child(child.name), "$fullName/")
} else if (item == null) {
// this code is never reached, non-existing projects generate an exception
println "Deleting (no such job): '$fullName'"
child.deleteRecursive()
} else if (item instanceof Job && !item.isBuildable()) {
// don't remove the workspace for disabled jobs!
//println "Deleting (job disabled): '$fullName'"
//child.deleteRecursive()
}
} catch (Exception exc) {
println " Exception happened: " + exc.message
println " So we delete '" + child + "'!"
child.deleteRecursive()
}
}
}
println "Beginning of cleanup script."
// loop over possible slaves
for (node in Jenkins.instance.nodes) {
println "Processing $node.displayName"
def workspaceRoot = node.rootPath.child("workspace");
deleteUnusedWorkspace(workspaceRoot, "")
}
// do the master itself
deleteUnusedWorkspace(Jenkins.instance.rootPath.child("workspace"), "")
println "Script has completed."
雖然可能需要一些個人調整。 很明顯,您應該先運行這個腳本,並將所有刪除語句註釋掉,並確保在進行實際運行之前有備份。
是的......這是最終的回退。我希望有一個更簡單的解決方案。 – 2012-07-09 03:40:42