reference:
- Script Console
- Jenkins Features Controlled with System Properties
- Jenkins : Jenkins Script Console
- Jenkins : Use Jenkins
- Java API Usage Example
- I have a stuck Pipeline and I can not stop it
- scripts:
- * jenkinsci/jenkins-scripts
- * cloudbees/jenkins-scripts
- * dnozay/_Jenkins+Script+Console.md
- * mubbashir/Jenkins+Script+Console.md
- Jenkins script
- Sam Gleske’s jenkins-script-console-scripts repository
- Sam Gleske’s jenkins-bootstrap-shared repository
- Some scripts at JBoss.org
- mikejoh/jenkins-and-groovy-snippets.md
- samrocketman/jenkins-script-console-scripts
- others
- Jenkins : Monitor and Restart Offline Slaves
- Jenkins : Monitoring Scripts
- Jenkins : Printing a list of credentials and their IDs
- Jenkins : Wipe workspaces for a set of jobs on all nodes
- Jenkins : Invalidate Jenkins HTTP sessions
- Jenkins : Grant Cancel Permission for user and group that have Build permission
- python
[!TIP] to list methods on a class instance:
thing.metaClass.methods*.name.sort().unique()
to determine a class from an instance:
thing.class // or thing.getClass()
script console
usage
[!TIP]
- if you authenticate your API calls with a username and a user API token then a crumb is not required from Jenkins 2.96
$ SERVER="https://localhost:8080" $ COOKIEJAR="$(mktemp)" $ CRUMB=$(curl -u "admin:admin" -s --cookie-jar "$COOKIEJAR" "$SERVER/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,%22:%22,//crumb)") # to run script via curl $ curl -d "script=System.getProperties()" \ -u "admin:admin" \ --cookie "$COOKIEJAR" \ -H "$CRUMB" \ https://${SERVER}/scriptText
- or
$ SERVER="https://localhost:8080" $ COOKIEJAR="$(mktemp)" $ CRUMB=$(curl -u "admin:admin" \ --cookie-jar "${COOKIEJAR}" \ 'https://${SERVER}/crumbIssuer/api/json' | jq -r '[.crumbRequestField, .crumb] | join(":")' ) # verify $ echo $CRUMB Jenkins-Crumb:c11dc*******************************************************e463 $ curl -d "script=System.getProperties()" \ -u "admin:admin" \ -s \ --cookie "$COOKIEJAR" \ -H "$CRUMB" \ https://${SERVER}/scriptText $ curl --data-urlencode "script=$(< ./script.groovy)" \ -s \ --netrc-file ~/.netrc \ --cookie "${COOKIEJAR}" \ -H "${CRUMB}" \ https://${SERVER}/scriptText
remote access
$ curl -d "script=<your_script_here>" https://jenkins/script # or to get output as a plain text result (no HTML) $ curl -d "script=<your_script_here>" https://jenkins/scriptText
curl submitting groovy file
$ curl --data-urlencode "script=$(< ./somescript.groovy)" https://jenkins/scriptText
- via api token
$ curl --user 'username:api-token' \ --data-urlencode \ "script=$(< ./somescript.groovy)" \ https://jenkins/scriptText
- via python
with open('somescript.groovy', 'r') as fd: data = fd.read() r = requests.post('https://jenkins/scriptText', auth=('username', 'api-token'), data={'script': data})
- via api token
setup system property (temporary)
[!TIP|label:references:]
timestampe
System.setProperty( 'org.apache.commons.jelly.tags.fmt.timeZone', 'America/Los_Angeles' )
-
System.setProperty( 'org.jenkinsci.plugins.durabletask.BourneShellScript.HEARTBEAT_CHECK_INTERVAL', 36000 )
to clear property
System.clearProperty( 'hudson.model.DirectoryBrowserSupport.CSP' )
to get property
System.getProperty( 'hudson.model.DirectoryBrowserSupport.CSP' )
to get all properties
System.getProperties() // or System.getProperties().sort().collectEntries{[ (it.key), (it.value) ]} System.getProperties().sort().each { println "${it.key} ~> ${it.value}" } System.getProperties().sort().collect{ "${it.key} ~> ${it.value}" }.join('\n')
extend built-in node executor
import jenkins.model.*
jenkins.model.Jenkins.instance.setNumExecutors(5)
execute shell script in console
[!TIP|label:references:]
println ( 'uname -a'.execute().text )
// or
println ( 'printenv'.execute().in.text )
result
Linux devops-jenkins-685cf57df9-znfs8 4.19.12-1.el7.elrepo.x86_64 #1 SMP Fri Dec 21 11:06:36 EST 2018 x86_64 GNU/Linux
or
import hudson.util.RemotingDiagnostics import jenkins.model.Jenkins String agentName = 'your agent name' // groovy script you want executed on an agent groovyScript = ''' println System.getenv("PATH") println "uname -a".execute().text '''.stripIndent() String result jenkins.model.Jenkins.instance.slaves.find { agent -> agent.name == agentName }.with { agent -> result = RemotingDiagnostics.executeGroovy( groovyScript, agent.channel ) } println result
read & write files
// write
new File('/tmp/file.txt').withWriter('UTF-8') { writer ->
try {
writer << 'hello world\n'
} finally {
writer.close()
}
}
// read
new File('/tmp/file.txt').text
write file in agent
import hudson.FilePath import hudson.remoting.Channel import jenkins.model.Jenkins String agentName = 'some-agent' String filePath = '/tmp/file.txt' Channel agentChannel = jenkins.model.Jenkins.instance.slaves.find { agent -> agent.name == agentName }.channel new FilePath( agentChannel, filePath ).write().with { os -> try { os << 'hello world\n' } finally { os.close() } }
read file from an agent
import hudson.FilePath import hudson.remoting.Channel import jenkins.model.Jenkins import java.io.BufferedReader import java.io.InputStreamReader import java.nio.charset.StandardCharsets import java.util.stream.Collectors String agentName = 'some-agent' String filePath = '/tmp/file.txt' Channel agentChannel = jenkins.model.Jenkins.instance.slaves.find { it.name == agentName }.channel String fileContents = '' new FilePath(agentChannel, filePath).read().with { is -> try { fileContents = new BufferedReader( new InputStreamReader(is, StandardCharsets.UTF_8)) .lines() .collect(Collectors.joining("\n") ) } finally { is.close() } } // with // print contents of the file from the agent println '===' println(fileContents) println '==='
nslookup
[!NOTE|label:references:]
if( !binding.hasVariable('domain') ) {
domain = 'example.com'
}
if( !(domain in String) ) {
throw new Exception('PARAMETER ERROR: domain must be a string.')
}
InetAddress dnsInetAddress = InetAddress.getByName domain
println dnsInetAddress.hostAddress
jenkins system
import jenkins.model.*;
import org.jenkinsci.main.modules.sshd.*;
jenins.model.Jenkins instance = jenkins.model.Jenkins.instance
instance.setDisableRememberMe( false )
instance.setNumExecutors( 2 )
instance.setSystemMessage( '<h2>welcome to the Jenkins Master</h2>' )
instance.setRawBuildsDir()
instance.save()
def sshd = SSHD.get()
sshd.setPort( 12345 )
sshd.save()
get system info
println( "Groovy: ${GroovySystem.version}" )
println( "Jenkins: ${jenkins.model.Jenkins.instance.getVersion()}" )
println( "OS: ${System.getProperty('os.name')} - ${System.getProperty('os.version')}" )
println( "Java: ${System.getProperty('java.version')} - ${System.getProperty('java.vm.vendor')} (${System.getProperty('java.vm.name')})" )
println "---"
jenkins.model.Jenkins.instance.pluginManager.plugins
.collect()
.sort { it.getShortName() }
.each {
plugin -> println("${plugin.getShortName()}:${plugin.getVersion()}")
}
return
modify log level
System.setProperty( 'org.apache.commons.logging.Log', 'org.apache.commons.logging.impl.SimpleLog' );
System.setProperty( 'org.apache.commons.logging.simplelog.showdatetime', 'true' );
System.setProperty( 'org.apache.commons.logging.simplelog.log.httpclient.wire.header', 'error' );
System.setProperty( 'org.apache.commons.logging.simplelog.log.org.apache.http', 'error' );
System.setProperty( 'log4j.logger.org.apache.http', 'error' );
System.setProperty( 'log4j.logger.org.apache.http.wire', 'error' );
System.setProperty( 'org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient', 'error' );
- check log level
println System.getProperty( 'org.apache.commons.logging.Log' ); println System.getProperty( 'org.apache.commons.logging.simplelog.showdatetime' ); println System.getProperty( 'org.apache.commons.logging.simplelog.log.httpclient.wire.header' ); println System.getProperty( 'org.apache.commons.logging.simplelog.log.org.apache.http' ); println System.getProperty( 'log4j.logger.org.apache.http' ); println System.getProperty( 'log4j.logger.org.apache.http.wire' ); println System.getProperty( 'org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient' );
RABC
[!NOTE|label:references:]
jobs & builds
[!TIP|label:get more:]
list build status with percentage
- get all builds result percentage
- get builds result percentage within 24 hours
- get builds result and percentage within certain start-end time
get all builds status during certain start-end time
- list all builds within 24 hours
- get last 24 hours failure builds
- get last 24 hours failure builds via Map structure
- get builds result during certain start-end time
- get builds result and percentage within certain start-end time
list builds which running for more than 24 hours
- list job which running for more than 24 hours
- get last 24 hours failure builds
- get last 24 hours failure builds via Map structure
- get builds result percentage within 24 hours
- get builds result during certain start-end time
- get builds result and percentage within certain start-end time
get workspace
hudson.FilePath workspace = hudson.model.Executor.currentExecutor().getCurrentWorkspace()
- get absolute path
println( "script directory: ${new File(__FILE__).parent.absolutePath}" )
shelve jobs
// you have to install the Shelve Project Plugin on your Jenkins Master
// the maximum value for daysBack is 365, going beyond 365 will break the script.
import org.jvnet.hudson.plugins.shelveproject.ShelveProjectTask
def daysBack = 365;
jenkins.model.Jenkins.instance.getAllItems( AbstractProject.class ).each { it ->
def lastBuild = it.getLastBuild()
if( lastBuild != null ) {
def back = Calendar.getInstance()
back.set( Calendar.DAY_OF_YEAR,back.get(Calendar.DAY_OF_YEAR) - daysBack )
if ( lastBuild.getTime().compareTo(back.getTime()) < 0 ) {
println it.name + " was built over " + daysBack + " days ago: " + lastBuild.getTime()
if ( it instanceof AbstractProject ){
def spt= new ShelveProjectTask(it)
Hudson.getInstance().getQueue().schedule(spt , 0 );
} else {
println it.name + " was not shelved ----------- "
}
}
}
}
plugins
via api : imarslo: list plugins
simple list
jenkins.model.Jenkins.instance
.pluginManager
.plugins
.each { plugin ->
println ( "${plugin.getDisplayName()} (${plugin.getShortName()}): ${plugin.getVersion()}" )
}
list for helm-value.yaml
jenkins.model.Jenkins.instance
.pluginManager
.plugins
.sort(false) { a, b ->
a.getShortName().toLowerCase() <=> b.getShortName().toLowerCase()
}
.each { plugin ->
println "- ${plugin.getShortName()}:${plugin.getVersion()}"
}
"DONE"
with delegate to Servlet container security realm
ExtensionList.lookup( UnprotectedRootAction ).each {
println String.format( "URL: '%s/' provided by '%s' in '%s'",
it.urlName,
Jenkins.get().pluginManager.whichPlugin(it.class)?.shortName?:"Jenkins Core",
it.class.name
)
}
list plugin and dependencies
println jenkins.model.Jenkins.instance.pluginManager.plugins
.sort(false) { a, b ->
a.getShortName().toLowerCase() <=> b.getShortName().toLowerCase()
}
.collect { plugin ->
"~~> ${plugin.shortName} : ${plugin.version} : ${plugin.displayName}" +
( plugin.dependants ? "\n\t+++ ${plugin.dependants.join('\n\t+++ ')}" : '' ) +
( plugin.dependencies ? "\n\t... ${plugin.dependencies.join('\n\t... ')}" : '' )
}
.join('\n')
get specific plugin dependencies
List<String> keywords = [ 'jsch' ] println jenkins.model.Jenkins.instance.pluginManager.plugins .findAll { plugin -> keywords.any { it == plugin.shortName } } .sort(false) { a, b -> a.getShortName().toLowerCase() <=> b.getShortName().toLowerCase() } .collect { plugin -> "~~> ${plugin.shortName} : ${plugin.version} : ${plugin.displayName}" + ( plugin.dependants ? "\n\t+++ ${plugin.dependants.join('\n\t+++ ')}" : '' ) + ( plugin.dependencies ? "\n\t... ${plugin.dependencies.join('\n\t... ')}" : '' ) } .join('\n')
get dependency tree
import hudson.PluginWrapper def getDependencyTree( String keyword, Integer benchmark = 2, Integer index = 0 ) { String prefix = index ? '\t' + "|\t"*(index-1) + "|... " : '' PluginWrapper plugin = jenkins.model.Jenkins.instance.pluginManager.plugins.find { keyword == it.shortName } List dependencies = plugin.collect { it.dependencies }.flatten() ?: [] println prefix + "${plugin.shortName} ( ${plugin.version} )" if ( dependencies && benchmark != index ) { dependencies.collect{ it.shortName }.each { getDependencyTree (it, benchmark, index+1) } } } getDependencyTree( 'jsch', 100 ) "DONE"
- result
jsch ( 0.2.8-65.v052c39de79b_2 ) |... ssh-credentials ( 305.v8f4381501156 ) | |... credentials ( 1254.vb_96f366e7b_a_d ) | | |... structs ( 324.va_f5d6774f3a_d ) | | | |... javax-activation-api ( 1.2.0-6 ) | | | |... javax-mail-api ( 1.6.2-9 ) | | | | |... javax-activation-api ( 1.2.0-6 ) | | | |... instance-identity ( 173.va_37c494ec4e5 ) | | | | |... bouncycastle-api ( 2.28 ) | | |... configuration-as-code ( 1647.ve39ca_b_829b_42 ) | | | |... caffeine-api ( 3.1.6-115.vb_8b_b_328e59d8 ) | | | |... commons-text-api ( 1.10.0-36.vc008c8fcda_7b_ ) | | | | |... commons-lang3-api ( 3.12.0-36.vd97de6465d5b_ ) | | | | | |... javax-activation-api ( 1.2.0-6 ) | | | | | |... javax-mail-api ( 1.6.2-9 ) | | | | | | |... javax-activation-api ( 1.2.0-6 ) | | | | | |... instance-identity ( 173.va_37c494ec4e5 ) | | | | | | |... bouncycastle-api ( 2.28 ) | | | |... snakeyaml-api ( 1.33-95.va_b_a_e3e47b_fa_4 ) | |... trilead-api ( 2.84.v72119de229b_7 ) | |... instance-identity ( 173.va_37c494ec4e5 ) | | |... bouncycastle-api ( 2.28 ) |... trilead-api ( 2.84.v72119de229b_7 ) |... javax-activation-api ( 1.2.0-6 ) |... javax-mail-api ( 1.6.2-9 ) | |... javax-activation-api ( 1.2.0-6 ) |... instance-identity ( 173.va_37c494ec4e5 ) | |... bouncycastle-api ( 2.28 )
- result
-
def plugins = jenkins.model.Jenkins.instance .pluginManager .plugins .sort(false) { a, b -> a.getShortName().toLowerCase() <=> b.getShortName().toLowerCase() } println "jenkins instance : ${jenkins.model.Jenkins.instance.getComputer('').hostName} + ${jenkins.model.Jenkins.instance.rootUrl}\n" + "installed plugins:\n==================" plugins.each { plugin -> println " ${plugin.getShortName()} : ${plugin.getVersion()} | ${plugin.getDisplayName()}" } println "\nplugins dependency tree (...: dependencies; +++: dependants) :\n=======================" plugins.each { plugin -> println """ ${plugin.getShortName()} : ${plugin.getVersion()} | ${plugin.getDisplayName()} +++ ${plugin.getDependants()} ... ${plugin.getDependencies()} """ }
or
def jenkins = jenkins.model.Jenkins.instance println """ Jenkins Instance : ${jenkins.getComputer('').hostName} + ${jenkins.rootUrl} Installed Plugins: ================== """ jenkins.pluginManager .plugins .sort(false) { a, b -> a.getShortName().toLowerCase() <=> b.getShortName().toLowerCase() }.each { plugin -> println "${plugin.getShortName()}: ${plugin.getVersion()} | ${plugin.getDisplayName()}" } println """ Plugins Dependency tree (...: dependencies; +++: dependants) : ======================= """ jenkins.pluginManager .plugins .sort(false) { a, b -> a.getShortName().toLowerCase() <=> b.getShortName().toLowerCase() }.each { plugin -> println """ ${plugin.getShortName()} : ${plugin.getVersion()} | ${plugin.getDisplayName()} +++ ${plugin.getDependants()} ... ${plugin.getDependencies()} """ }
scriptApproval
backup & restore all scriptApproval items
backup
import java.lang.reflect.* import jenkins.model.Jenkins import jenkins.model.* import org.jenkinsci.plugins.scriptsecurity.scripts.* import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.* import static groovy.json.JsonOutput.* scriptApproval = ScriptApproval.get() alreadyApproved = new HashSet<>(Arrays.asList(scriptApproval.getApprovedSignatures())) println prettyPrint( toJson(alreadyApproved.sort()) )
restore
def scriptApproval = org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval.get() String[] signs = [ 'method org.jenkinsci.plugins.workflow.steps.FlowInterruptedException getCauses' , 'method org.jenkinsci.plugins.workflow.support.steps.input.Rejection getUser' ] for( String sign : signs ) { scriptApproval.approveSignature( sign ) } scriptApproval.save()
-
import java.lang.reflect.*; import jenkins.model.Jenkins; import jenkins.model.*; import org.jenkinsci.plugins.scriptsecurity.scripts.*; import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.*; import static groovy.json.JsonOutput.* ScriptApproval scriptApproval = ScriptApproval.get() HashSet<String> alreadyApproved = new HashSet<>(Arrays.asList(scriptApproval.getApprovedSignatures())) Closure approveSignature = { String signature -> if ( ! alreadyApproved?.contains(signature) ) scriptApproval.approveSignature( signature ) } [ 'field org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval$PendingSignature dangerous' , 'field org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval$PendingSignature signature' , 'method org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval$PendingThing getContext' , 'method org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval approveSignature java.lang.String' , 'method org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval getPendingScripts' , 'method org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval getPendingSignatures' , 'staticMethod org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval get' , 'staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods flatten java.util.Set' , 'method org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper getRawBuild' ].each { println "~~> ${it}"; approveSignature(it) } scriptApproval.save()
Jenkinsfile
#!/usr/bin/env groovy import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval timestamps { ansiColor('xterm') { def requester = currentBuild.rawBuild.getCause(UserIdCause.class)?.getUserId() ?: 'jenkins' final List<String> description = [] try { ScriptApproval scriptApproval = ScriptApproval.get() final LinkedHashSet<String> pendingScripts = new HashSet<>(Arrays.asList( scriptApproval.getPendingScripts() )).flatten() final LinkedHashSet<String> pendingSignature = new HashSet<>(Arrays.asList( scriptApproval.getPendingSignatures() )).flatten() if ( ! pendingScripts && ! pendingSignature ) { currentBuild.description = 'NOT_BUILT: nothing can be approved' currentBuild.rawBuild.executor.interrupt( Result.NOT_BUILT ) } if ( pendingScripts ) { println 'scripts pending approval ...' pendingScripts.collect().each { ps -> String log = "${ps.context.user}@${ps.context.psem.fullName} : ${ps.hash} ( ${ps.language.class.simpleName} )" description << log println "~~> ${log}. scripts: \n ${ps.script}" scriptApproval.approveScript( ps.hash ) } scriptApproval.save() } // pendingScripts if ( pendingSignature ) { println 'signatures pending approval ...' pendingSignature.collect().each { ps -> String signature = ps.signature if ( ! ps.dangerous ) { description << signature println "~~> '${signature}'" scriptApproval.approveSignature( signature ) } else { println "~~> '${signature}' is too dangerous to be approval automatically. contact with Jenkins administrator." } scriptApproval.save() } } } catch(e) { def sw = new StringWriter() e.printStackTrace( new PrintWriter(sw) ) echo sw.toString() throw e } finally { if ( description ) { currentBuild.description = "@${requesterId} " + "${buildResults.isSuccess(currentBuild.currentResult) ? 'successful' : 'failed to'} " + "approved : '${description.join('; ')}'" } } // try/catch/finally }} // ansiColor | timestamps // vim:tabstop=2:softtabstop=2:shiftwidth=2:expandtab:filetype=Jenkinsfile
automatic approval
// libs.groovy def autoAccept( Closure body ) { try { body() } catch ( org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException e ) { String msg = "NOT_BUILT : interrupted by approval scripts or signature" def cause = { msg as String } as CauseOfInterruption currentBuild.rawBuild.executor.interrupt( Result.NOT_BUILT, cause ) currentBuild.description = msg build wait: false, job: '/marslo/scriptApproval' } } // jenkinsfile libs.autoAccept() { ...content... }
automatic approval all pending
-
import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval ScriptApproval scriptApproval = ScriptApproval.get() scriptApproval.pendingScripts.each { scriptApproval.approveScript( it.hash ) }
job dsl support for scriptapproval
import jenkins.model.Jenkins def scriptApproval = jenkins.model.Jenkins.instance .getExtensionList('org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval')[0] def hashesToApprove = scriptApproval.pendingScripts .findAll{ it.script.startsWith(approvalPrefix) } .collect{ it.getHash() } hashesToApprove.each { scriptApproval.approveScript(it) }
disable the scriptApproval
[!NOTE|label:@deprecated]
- file:
$JENKINS_HOME/init.groovy.d/disable-script-security.groovy
import javaposse.jobdsl.plugin.GlobalJobDslSecurityConfiguration
import jenkins.model.GlobalConfiguration
// disable Job DSL script approval
GlobalConfiguration.all().get(GlobalJobDslSecurityConfiguration.class).useScriptSecurity=false
GlobalConfiguration.all().get(GlobalJobDslSecurityConfiguration.class).save()