Barth
Barth

Reputation: 15715

How can I remove a Jenkins log but keep build?

We have builds that generate a lot of logs. It takes space thus we have to tell Jenkins to remove old builds. It is a problem because we therefore lose the long-term statistics.

I am thinking of removing or emptying the "log" file of each build older than a week and tell Jenkins not to delete old build.

Is there a clean way of achieving the same ?

Upvotes: 6

Views: 16226

Answers (4)

ranma2913
ranma2913

Reputation: 1206

I wanted to share another script I use:

import hudson.model.Job
import jenkins.model.Jenkins

// Delete old logs that fills up the disk on the master node.
// Run this from the Jenkins console (Manage Jenkins, Manage Nodes, master, Script Console)

//def itemNameMatcher = "/"
//def itemNameMatcher = "Fortify_Scan/covid-portal/"
def itemNameMatcher = "Sonar_Scan/"
def numBuildsKeepLogs = 2

def totalSize = 0
println("************************************************** START ***************************************************************")
Jenkins.instance.getAllItems(Job.class).each { job ->
    if ((job.fullName =~ itemNameMatcher).find()) {
        def recent = job.getBuilds().limit(numBuildsKeepLogs)
        for (build in job.getBuilds()) {
            if (!recent.contains(build)) {
                try {
                    File logFile = build.getLogFile()
                    totalSize += logFile.length()
                    println("$logFile, ${logFile.length()}")
                    logFile.delete()
                    logFile.createNewFile()
                }catch(e){
                    println("Unable to delete the log for $build. An exception happened: $e")
                }
            }
        }
    }
}
println "Total size: ${totalSize}"
return "************************************************* END ******************************************************************"

Upvotes: 0

snowe
snowe

Reputation: 1375

Surprised that this isn't a plugin, but using Caleb's answer I extended it to fit our case. There are a lot of missing details here and stuff has changed in Jenkins in the past few years, so I'm creating a new answer.

  1. Make sure you have a groovy installation declared, under Jenkins > Global Tool Configuration > Groovy.

image showing groovy installation screen in Jenkins

  1. Create a new Freestyle job (I called ours clean-logs).
  2. Under Build Triggers, set Build Periodically to H H * * * to run every day.
  3. Under Build > Add build step choose Execute system Groovy script.

DO NOT CHOOSE Execute Groovy Script. This will lead to a lot of swearing.

  1. Choose Groovy Command and then paste this script in:
import hudson.model.*;
import jenkins.model.*;
def days = 3
Jenkins.instance.getAllItems(Job.class).each{ 
  println "deleting logs for " + it.name + " - " + it.class
  it.getBuilds().byTimestamp(1, System.currentTimeMillis() - (1000L * 60 * 60 * 24 * days)).each { it.getLogFile().delete(); it.getLogFile().createNewFile() }
}

This script will now run every day and delete logs older than 3 days old for all projects in Jenkins. It will also log which projects it's cleaning up. If you would like to skip projects simply match against the job name and skip.

The final setup will look like this:

image showing above specified configuration


Gotchas I encountered trying to figure this out.

  • You must specify import hudson.model.*; and import jenkins.model.*;
  • You must use Execute system Groovy script, not Execute Groovy Script

Upvotes: 2

Caleb
Caleb

Reputation: 31

Haven't found a really clean way that exists yet, but using groovy from within Jenkins is arguably cleaner than deleting from the filesystem outside of Jenkins.

This example groovy script will delete all logs from builds of the "test_dummy" job that are older than 180 days.

import jenkins.model.*;
def days = 180
def jobName = "test_dummy"
def j = Jenkins.instance.getItemByFullName(jobName);
j.getBuilds().byTimestamp(1, System.currentTimeMillis() - (1000L * 60 * 60 * 24 * days)).each { it.getLogFile().delete(); it.getLogFile().createNewFile() }

So get the job, get all the builds for it in your timestamp range, then get and delete all the log files. I'm also going and creating an empty file in their place, though I'm sure if I dug deeper I could find a way just to truncate to 0.

Using Jenkins getJobNames(), you could get all the jobs in Jenkins and then loop through them if you wanted. Depending on how you do backups, you could tie it to run before you do backups to save space.

Upvotes: 3

Andy Chen
Andy Chen

Reputation: 361

I saw there is a Delete Log Plugin but I didn't personally use it.

https://wiki.jenkins-ci.org/display/JENKINS/Delete+log+plugin

However in my work I did similar thing by just create another job, which go to the Jenkins master server, sort the builds, pick up the ones that need to be cleaned up, and remove the log file. Should be faily easy to do with any scripting language.

Upvotes: 3

Related Questions