2012-07-09 31 views
3

我們有八個節點哈德森集羣。當一個特定的代碼分支不再積極利用,我們禁用的構建工作,但該作業的工作空間仍然流連佔用空間中的所有節點上。如何觸發哈德森的人工清理工作區

我正在尋找一種方式來觸發在所有節點的工作空間的清理。請注意,我沒有在「構建之前」找到「乾淨的工作區」解決方案。

回答

0

這聽起來像你「禁用時所建刪除工作區」的解決方案尋找。你可以寫一個哈德森插件來做到這一點。這可能是過度殺傷。

如果我不得不這樣做(這我不會因爲我們沒有磁盤空間不足),我會寫一個腳本單位找哈德森目錄下的所有殘疾人的就業機會。作業由XML文件表示。然後,我會讓腳本刪除任何匹配的工作區。我可能會在cron中設置它,所以它每晚或每週運行一次,或者在環境中適當運行。

+0

是的......這是最終的回退。我希望有一個更簡單的解決方案。 – 2012-07-09 03:40:42

4

你並不需要編寫一個插件。您可以編寫一個利用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將自動在矩陣作業中指定的所有從站上運行它。

+2

那麼,我將使用哪個API來操作各種構建節點上的工作區。迭代工作並檢查他們的狀態很簡單,但並沒有讓我走得很遠。我需要一個循環遍歷所有節點的內部循環,以某種方式檢查該節點是否實際上具有該作業的工作區,以及是否以某種方式刪除它。最後一部分可能是最具挑戰性的,除非Hudson已經有API在給定節點上刪除Job的工作區。 – 2012-07-09 19:33:23

+1

看起來您需要迭代節點並使用[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

3

我曾嘗試下面的腳本,它適用於單個節點,

def hi = hudson.model.Hudson.instance 
      hi.getItems(hudson.model.Job).each { 
       job -> 
       if(job.isDisabled()) 
       { 
        println(job.displayName) 
        job.doDoWipeOutWorkspace() 
       } 
      } 
2

以下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") 
    } 
} 
+0

我在寫一個清理腳本並使用上面的代碼作爲模板。令人驚訝的是,「master」不是getNodes()返回的節點之一嗎?主工作區是如何找到的? – Frank 2013-10-11 20:10:38

+0

在這裏回答我自己的問題:關閉Hudson實例getComputer(「」)。getNode()。 。 。將該節點添加到getNodes()列表中,看起來我很好。 – Frank 2013-10-11 22:37:48

1

它有點晚,但我遇到了同樣的問題。我的腳本會檢查是否有至少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) 
    } 
} 
+0

「size = rootPath.asCallableWith({f,c - > f.getUsableSpace()} as FileCallable).call()」對我崩潰:java.io.IOException:無法序列化[email protected] – 2014-01-11 15:12:23

+0

我嘗試修復:https://gist.github.com/rb2k/8372402 – 2014-01-11 15:42:42

1

我最近也在尋找清理我的詹金斯的工作空間,但有一點扭曲:我想僅從不再存在就業刪除工作區。這是因爲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." 

雖然可能需要一些個人調整。 很明顯,您應該先運行這個腳本,並將所有刪除語句註釋掉,並確保在進行實際運行之前有備份。