The Jenkins server these are written for hasn't (can't) been updated since 2017. So some commands are probably deprecated in current versions.
These scripts are all written to run from the /jenkins/script Script Console.
| /* ******************************************************************************************************** | |
| * This is the working script from 3/12/20@0049. | |
| * I'm working on classing this up. For now there's basically two operations. | |
| * getFreespace -- no parameter method that prints the date and the results of "df -h" | |
| * cleaner -- takes the Jenkins job name, the filename portions before the counter, after, | |
| * and the map key of the pattern to get the counter. | |
| * >> cleaner deletes matching files from the job's build folders except for the highest counter file. | |
| * it also skips false matches (if the filename has an extra prefix or suffix) and no match files. | |
| * Note: it does not delete the workspace folder yet. You'll have to do that manually. | |
| /* ********************************************************************************************************/ | |
| def getFreespace(){println "date".execute().text; println "df -h".execute().text;} | |
| def doit(java.lang.Process one){ | |
| pone=one; pone.waitFor(); if (pone.exitValue()) { println pone.err.text } else { println pone.text }; | |
| } | |
| def proc(String string) { string.execute() } | |
| def ls(String path){ proc("ls ${path}") } | |
| def lsa(String path){ proc("ls -lA ${path}") } | |
| def rm(String path){ proc("rm ${path}") } | |
| def rem(def nums, String path, String prefix, String suffix, def build){ | |
| println("\n[Build ${build}] ${path}");doit(lsa(path)); | |
| if( nums.size()>1 ){ nums.each{ doit(rm(path+prefix+it+suffix)) } } | |
| doit(lsa(path)); | |
| } | |
| def getBuildDirNums(def path){ | |
| lsa(path).text.split(/\r?\n/).findAll{it.find(~/(?:^d.*)\s([0-9]+)$/)}.collect{it.split(/\s/)[-1].toInteger()}.sort() | |
| } | |
| def getFileNums(def path, def pattern){ | |
| ls(path).text.findAll(pattern).collect{it.split('-')[1].toInteger()}.sort(); | |
| } | |
| def cleaner(def job, def prefix, def suffix, def numPattern){ | |
| def jhome = "/opt/bitnami/apps/jenkins/jenkins_home/"; | |
| def b = [jhome,"jobs/",job,"/builds/",null,"/archive/target/"]; | |
| def ws = [jhome,"workspace/",job,"/target/"] | |
| def fp = [branch:~/(?:master-)([0-9]+)/,version:~/(?:1.0.0-)([0-9]+)/,bdir:~/(?:^d.*)\s([0-9]+)$/,newline:~/\r?\n/]; | |
| def builds = b[0..3].join(); def bdirs = getBuildDirNums(builds); | |
| bdirs.each{ def files = ls(builds+it+b[-1]).text; if (files) { | |
| def n = getFileNums(builds+it+b[-1],fp.version); n?.pop(); | |
| rem(n, builds+it+b[-1], prefix, suffix, it)} | |
| } | |
| } | |
| // -------------------- variables ---------------------------- // | |
| def job = "deploy-X-v1" | |
| def prefix = "X"+"-1.0.0-master-";def suffix = ".jar"; | |
| cleaner(job, prefix, suffix, "fp.pattern.name") | |
| //getFreespace() |
| #!/bin/sh | |
| # This was created to deal with existing legacy issues. It's run after the Copy-Artifact-Plugin copies a stack of artifacts from a build(dev) pipeline. It copies the highest build number (artifacts are versioned with BRANCH-pomversion-BUILD_NUMBER) artifact to a statical filename. Then further promotions only need to deal with that static filename. The pom.xml has the proper version number for this specific build. | |
| cp $(find ./target -maxdepth 1 -regex ".+-$(ls target/*.jar | perl -n -e'/.+-(\d+)-.+/ && print "$1\n"' | sort -r -n | head -n1)-.+\.jar" -printf 'target/%P' -quit) target/last_successful_app.jar |
| // not sure where this came from either | |
| import hudson.node_monitors.* | |
| import hudson.slaves.* | |
| import Jenkins.* | |
| nByte = 0 | |
| nByteDir = 0 | |
| jenkins = Jenkins.instance | |
| for (slave in jenkins.nodes) { | |
| wsRoot = slave.getWorkspaceRoot() | |
| println( "Nodename: " + slave.getNodeName() ) | |
| for (dir in wsRoot.list()) { | |
| nByteDir = 0 | |
| println("=====================================================================") | |
| println(" dirname: " + dir ) | |
| showFiles( dir ) | |
| println(" Byte Dir: " + nByteDir ) | |
| } | |
| println("=====================================================================") | |
| println("Byte Total: " + nByte ) | |
| println("#####################################################################") | |
| } | |
| def showFiles( dir ) { | |
| for ( files in dir.list() ){ | |
| if( files.isDirectory() ) { | |
| showFiles( files ); | |
| } else { | |
| ByteCounter( files.length() ) | |
| } | |
| } | |
| } | |
| def ByteCounter ( c ) | |
| { | |
| nByte = nByte + c | |
| nByteDir = nByteDir + c | |
| } |
| //no comment | |
| J=[JENKINS_HOME:'/opt/bitnami/apps/jenkins/jenkins_home', | |
| workspace: 'workspace', | |
| builds: 'builds', | |
| archive: 'archive', | |
| target: 'target', | |
| jobs: 'jobs'] | |
| p=J.values() | |
| String sep='/' | |
| JOBS=['build-test-template','deploy-qa-template','deploy-uat-template-v1'] | |
| String WORKSPACE=J.JENKINS_HOME+sep+J.workspace+sep+JOBS[0]+sep | |
| String jobs=J.JENKINS_HOME+sep+J.jobs+sep | |
| String mjp=jobs+JOBS[0]+sep | |
| String mws=WORKSPACE | |
| String pathx=mws+p[2] | |
| String pathy=mjp+p[1..2].join('/') | |
| ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| //this | |
| ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| //does | |
| ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| //nothing | |
| ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| // TODO: rewrite this to handle any number of processes | |
| // I don't take credit for the core function here, I think I found it on reddit | |
| def doit(java.lang.Process one){ | |
| pone=one | |
| pone.waitFor() | |
| if (pone.exitValue()) { println pone.err.text } else { println pone.text } | |
| } | |
| //doit(lsa('~/.m2/repository'), grep('^d')) | |
| def doit(java.lang.Process pone, java.lang.Process ptwo){ | |
| pone | ptwo | |
| ptwo.waitFor() | |
| if (ptwo.exitValue()) { println ptwo.err.text } else { println ptwo.text } | |
| } | |
| def doit(java.lang.Process pone, java.lang.Process ptwo, java.lang.Process pfour){ | |
| pone | ptwo | pfour | |
| pfour.waitFor() | |
| if (pfour.exitValue()) { println pfour.err.text } else { return pfour } | |
| } | |
| def doit(java.lang.Process pone, java.lang.Process ptwo, java.lang.Process pthree, java.lang.Process pfour){ | |
| pone | ptwo | pthree | pfour | |
| pfour.waitFor() | |
| if (pfour.exitValue()) { println pfour.err.text } else { println pfour.text } | |
| } |
| //pulled from a couple different windows I had open | |
| ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| s=sed(term="total\\s([0-9]+)M", sub="\\1", g='g') | |
| doit(lsahr(tx), head(200)) | |
| //doit(lsah(mws),wc()) | |
| //doit(lsahr(tx), egrep("^total.*M"), s) | |
| ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| four=doit(lsahr(tx), egrep("^total.*M"), s) | |
| acc = 0 | |
| fs = four.text.split() | |
| //print fs | |
| //fs.each { acc += it as Integer } | |
| //println "total ${acc}M" | |
| ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| duh=du(tx) | |
| g=grep('^[0-9]*\\.[0-9]*M') | |
| //doit(duh, g, sort('-nr'), head(30)) |
| // utility one-liners mainly used with doit() | |
| def proc(String string) { string.execute() } | |
| def awk(String cmd){ proc("awk ${cmd}") } | |
| def du(String path){ proc("du -h ${path}") } | |
| def lsa(String path){ proc("ls -ltA ${path}") } | |
| def lsah(String path){ proc("ls -lthrA ${path}") } | |
| def lsahr(String path){ proc("ls -lthrAR ${path}") } | |
| def head(int lines){ proc("head -n${lines}") } | |
| def head(int lines, String filePath){ proc("head -n${lines} ${filePath}") } | |
| def tail(int lines){ proc("tail -n${lines}") } | |
| def tail(int lines, String filePath){ proc("tail -n${lines} ${filePath}") } | |
| def cat(String filePath){ proc("cat ${filePath}") } | |
| def find(String cmd){ proc("find ${cmd}") } | |
| def efind(String opts='./*', String exec){ proc("find ${opts} -exec ${exec} ;") } | |
| def find2(String path='./*', String opts){ proc("find ${path} -maxdepth 3 ${opts} -printf '%P\\n'") } | |
| def find3(String path='.', String opts='', String pattern){ proc("find ${path} ${opts} ${pattern} -printf '%P\\n'") } | |
| def rm(String path){ proc("rm ${path}") } //rm(cpath) | |
| def rmf(String path, String R=''){ proc("rm -f${R} ${path}") } //rmf(cpath, 'R') | |
| def grep(String pattern){ proc("grep \"${pattern}\"") } | |
| def egrep(String pattern){ proc("grep -E ${pattern}") } | |
| def cp(String src, String tgt=".") { proc("cp ${src} ${tgt}") } | |
| def sort(String opts){ proc("sort ${opts}") } | |
| def sed(String term, String sub='', String g=''){ proc("sed -E s,${term},${sub},${g}") } | |
| def wc(){ proc("wc -l") } |
| // The original version of this script is found here: | |
| // ref: https://support.cloudbees.com/hc/en-us/articles/215549798-Best-Strategy-for-Disk-Space-Management-Clean-Up-Old-Builds | |
| // -- | |
| // String dryRun: to only list the jobs which would be changed | |
| // int daysToKeep: If not -1, history is only kept up to this day. | |
| // int numToKeep: If not -1, only this number of build logs are kept. | |
| // int artifactDaysToKeep: If not -1, artifacts are only kept up to this day. | |
| // int artifactNumToKeep: If not -1, only this number of builds have their artifacts kept. | |
| dryRun="!true" | |
| daysToKeep = -1 | |
| numToKeep = -1 | |
| artifactDaysToKeep = -1 | |
| artifactNumToKeep = 5 | |
| LinkedList builds = [] | |
| LinkedList nevers = [] | |
| def rotatorStatus = [:] | |
| Jenkins.instance.getAllItems(Job).findAll{ !it.logRotator }.each { job -> | |
| if (job.isBuildable() | |
| && job.supportsLogRotator() | |
| && job.getProperty(jenkins.model.BuildDiscarderProperty) == null | |
| && !(job instanceof org.jenkinsci.plugins.workflow.job.WorkflowJob) ) // toggle to process workflow jobs, other jobs or all jobs | |
| { | |
| (job.getLastBuild()) ? builds.add(job) : nevers.add(job) | |
| if (!"true".equals(dryRun)) { | |
| // adding a property implicitly saves so no explicit one | |
| try { | |
| job.setBuildDiscarder(new hudson.tasks.LogRotator ( daysToKeep, numToKeep, artifactDaysToKeep, artifactNumToKeep)) | |
| rotatorStatus.put(job, "pass") | |
| } catch (Exception e) { | |
| // Some implementation like for example the hudson.matrix.MatrixConfiguration supports a LogRotator but not setting it | |
| println "[WARNING] Failed to update ${job.fullName} of type ${job.class} : ${e}" | |
| rotatorStatus.put(job, "fail") | |
| } | |
| } | |
| } | |
| } | |
| builds.sort({a,b -> b.getLastBuild().getTimeInMillis() <=> a.getLastBuild().getTimeInMillis()}).each { | |
| println "[${rotatorStatus[it]}] ${it.getLastBuild().getTime()} -- ${it.fullDisplayName}" | |
| } | |
| println " - - - - - - - - - - - -" | |
| nevers.each { println "[${rotatorStatus[it]}] Never built once -- ${it.fullDisplayName}"} | |
| println "~fin~" |
| // this prints all the parameters for a job using a Jenkins API call | |
| // not sure where I copied this from | |
| import groovy.json.JsonSlurper | |
| def root = "<url to job>" | |
| def options = "/api/json?tree=builds[actions[parameters[name,value]],result,building,number,duration,estimatedDuration]" | |
| def jsonSlurper = new JsonSlurper() | |
| def text = new URL("${root}/${options}").text | |
| def data = jsonSlurper.parseText(text) | |
| data["builds"].each { buildsdata -> | |
| def result = buildsdata["result"] | |
| def num = buildsdata["number"] | |
| print("${root}/${num}/parameters |") | |
| buildsdata["actions"].each { actions -> | |
| if (actions["_class"].equals("hudson.model.ParametersAction")) { | |
| actions["parameters"].sort({it.name}).each { param -> | |
| print("${param.name}=${param.value}|") | |
| } | |
| } | |
| } | |
| println("") | |
| } | |
| --------------------------------------------------------------------------------------------------------- | |
| // get list of disabled jobs (I think...) | |
| jenkins.model.Jenkins.instance.getAllItems(jenkins.model.ParameterizedJobMixIn.ParameterizedJob.class) | |
| .findAll{job -> !(job.metaClass.methods*.name.findAll{method -> method == "isDisabled"}.isEmpty()) } | |
| .findAll{job -> job.disabled} | |
| .each{job -> | |
| def className = job.getClass(); | |
| def lastBuild = job.getLastBuild()? job.getLastBuild().number: "Never built once"; | |
| def lastBuildOnDate = job.getLastBuild()? job.getLastBuild().getTime():"Never built once" | |
| def url = job.getUrl() | |
| println "$url~$lastBuild~$lastBuildOnDate~$job.disabled" | |
| } |
| // These are some snippets that I plan to convert to one or two Jenkins jobs to help enforce our log-rotation policy | |
| // This will run log rotate on all Jenkins Jobs that have a log rotate stage/step defined | |
| Jenkins.instance.getAllItems(Job).findAll{ it.logRotator }.each { | |
| (it instanceof org.jenkinsci.plugins.workflow.job.WorkflowJob) && it.logRotator.perform(it) | |
| }; | |
| // I run this before and after any pruning actions to know how much space I've freed up | |
| // filename: getFreeSpace.groovy | |
| println "date".execute().text | |
| println "df -h".execute().text | |
| // test script while I was trying to get the cloudbees.folder nested jobs | |
| LinkedList builds = [] | |
| LinkedList nevers = [] | |
| job = Jenkins.instance.getItemByFullName("cloudbeesFolder/deploy-uat-template-v1") | |
| println "${job.name} of type ${job.class}" | |
| if (false && job.isBuildable() | |
| && job.supportsLogRotator() | |
| && job.getProperty(jenkins.model.BuildDiscarderProperty) == null | |
| && !(job instanceof org.jenkinsci.plugins.workflow.job.WorkflowJob) ) { | |
| println "no rotator set for \"${job.fullDisplayName}\" -- " + job.getClass() | |
| try { | |
| //job.setBuildDiscarder(new hudson.tasks.LogRotator ( daysToKeep, numToKeep, artifactDaysToKeep, artifactNumToKeep)) | |
| } catch (Exception e) { | |
| println "[WARNING] Failed to update ${job.fullName} of type ${job.class} : ${e}" | |
| } | |
| } else { | |
| builds.add(job) | |
| println "${builds[0].fullDisplayName} has a rotator already. lenth = ${builds.size()}" | |
| } |