8 つのノードを持つ Hudson クラスターがあります。特定のコード ブランチがアクティブに使用されなくなった場合、ビルド ジョブを無効にしますが、そのジョブのワークスペースは依然としてすべてのノードのスペースを占有します。
すべてのノードでワークスペースのクリーンアップをトリガーする方法を探しています。「ビルド前のクリーンなワークスペース」ソリューションを探しているわけではないことに注意してください。
8 つのノードを持つ Hudson クラスターがあります。特定のコード ブランチがアクティブに使用されなくなった場合、ビルド ジョブを無効にしますが、そのジョブのワークスペースは依然としてすべてのノードのスペースを占有します。
すべてのノードでワークスペースのクリーンアップをトリガーする方法を探しています。「ビルド前のクリーンなワークスペース」ソリューションを探しているわけではないことに注意してください。
プラグインを書く必要はありません。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 は、マトリックス ジョブで指定したすべてのスレーブでスクリプトを自動的に実行します。
次のスクリプトを試してみましたが、単一ノードで機能します。
def hi = hudson.model.Hudson.instance
hi.getItems(hudson.model.Job).each {
job ->
if(job.isDisabled())
{
println(job.displayName)
job.doDoWipeOutWorkspace()
}
}
次の 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")
}
}
少し遅れましたが、同じ問題に遭遇しました。私のスクリプトは、少なくとも 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)
}
}
私は最近、ジェンキンスのワークスペースをクリーンアップすることも検討していましたが、少しひねりを加えました。もう存在しないジョブからのみワークスペースを削除したかったのです。これは、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."
ただし、個別の微調整が必要な場合があります。明らかに、最初にすべての削除ステートメントをコメントアウトしてこのスクリプトを実行し、実際に実行する前にバックアップがあることを確認してください。
「ビルドを無効にするときにワークスペースを削除する」ソリューションを探しているようです。これを行うには、Hudson プラグインを作成できます。これはおそらくやり過ぎです。
これを行う必要がある場合 (ディスク容量が不足していないため、実行しません)、ユニット スクリプトを記述して、hudson ディレクトリの下にあるすべての無効なジョブを検索します。ジョブは XML ファイルで表されます。次に、一致するワークスペースをスクリプトで削除します。そして、おそらくcronで設定して、毎晩または毎週、または環境に適したものなら何でも実行できるようにします。