When running a Jenkins server with many jobs and many agents, you can quickly run out of disk space because of orphan workspaces:

• Jobs may roam on different agents, leaving a workspace on each
• Each concurrent job execution needs its own workspace
• When renaming or deleting a job, the workspaces may still survive on the disk (with the original job name)

With the Workspace Cleanup Plugin, the workspace may be deleted after a job execution (as post-build action), but this has other drawbacks:

• Every job execution needs a full SCM checkout (instead of an update), which can be very time-consuming
• If something goes wrong, there is no workspace for a post-mortem analysis

My solution is a simple Groovy script that iterates through all workspace directories on all agents, and deletes a workspace if it is older than one day:

def deleted = []
def oneDayAgo = new Date() - 1
jenkins.model.Jenkins.instance.nodes.each { hudson.model.Node node ->
node.workspaceRoot.listDirectories().each { hudson.FilePath path ->
def pathName = path.getRemote()
if (path.name.startsWith(".")) {
println "Skipping internal dir $node.displayName:$pathName"
} else {
def lastModified = new Date(path.lastModified())
if (lastModified < oneDayAgo) {
println "Deleting workspace at $node.displayName:$pathName (last modified $lastModified)" path.deleteRecursive() deleted << "$node.displayName:$pathName" } else { println "Skipping workspace at$node.displayName:$pathName (last modified$lastModified)"
}
}
}
}
"Deleted workspaces: \n\t" + deleted.sort().join("\n\t")


Of course this assumes that all jobs use the default workspace location.

This can either be executed with the Jenkins Script Console or as part of a scheduled maintenance job, using a System Groovy Script.