3

8 つのノードを持つ Hudson クラスターがあります。特定のコード ブランチがアクティブに使用されなくなった場合、ビルド ジョブを無効にしますが、そのジョブのワークスペースは依然としてすべてのノードのスペースを占有します。

すべてのノードでワークスペースのクリーンアップをトリガーする方法を探しています。「ビルド前のクリーンなワークスペース」ソリューションを探しているわけではないことに注意してください。

4

6 に答える 6

4

プラグインを書く必要はありません。Groovy プラグインを使用して 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)
}

この回答のコード スニペットも役立つ場合があります。彼らは 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))
  }

スクリプトはスレーブ自体で実行されるため、ワークスペースをスレーブから直接消去できます。もちろん、ワークスペースが存在しない場合もありますが、問題ありません。スクリプトは 1 回だけ作成することに注意してください。Jenkins は、マトリックス ジョブで指定したすべてのスレーブでスクリプトを自動的に実行します。

于 2012-07-09T08:21:03.497 に答える
4

次のスクリプトを試してみましたが、単一ノードで機能します。

  def hi = hudson.model.Hudson.instance
             hi.getItems(hudson.model.Job).each {
                job ->
                if(job.isDisabled())
                {
                   println(job.displayName)
                   job.doDoWipeOutWorkspace()
                 }
           }
于 2012-09-04T09:10:40.353 に答える
3

次の Groovy スクリプトは、すべてのノードで特定のジョブのワークスペースをワイプします。「Jenkins ホスト」/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")
  }
}
于 2013-08-09T09:39:21.957 に答える
1

少し遅れましたが、同じ問題に遭遇しました。私のスクリプトは、少なくとも 2 GB の空き容量があるかどうかを確認します。そうでない場合は、ノード上のすべてのワークスペースがクリアされてスペースが解放されます。

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)
    }
}
于 2013-10-22T11:59:56.937 に答える
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."

ただし、個別の微調整が必​​要な場合があります。明らかに、最初にすべての削除ステートメントをコメントアウトしてこのスクリプトを実行し、実際に実行する前にバックアップがあることを確認してください。

于 2016-10-18T07:29:54.810 に答える
0

「ビルドを無効にするときにワークスペースを削除する」ソリューションを探しているようです。これを行うには、Hudson プラグインを作成できます。これはおそらくやり過ぎです。

これを行う必要がある場合 (ディスク容量が不足していないため、実行しません)、ユニット スクリプトを記述して、hudson ディレクトリの下にあるすべての無効なジョブを検索します。ジョブは XML ファイルで表されます。次に、一致するワークスペースをスクリプトで削除します。そして、おそらくcronで設定して、毎晩または毎週、または環境に適したものなら何でも実行できるようにします。

于 2012-07-09T03:18:07.677 に答える