Dominando o Console de Script Groovy do Jenkins para Administração Avançada de Sistemas
Desbloqueie o poder oculto da administração do Jenkins usando o Console de Script Groovy. Este guia abrangente fornece scripts Groovy especializados e acionáveis para administradores de sistemas realizarem tarefas complexas instantaneamente, como atualizações em lote de configurações, gerenciamento imediato de agentes (desconexão/reconexão) e abortar forçosamente builds em execução. Aprenda a interagir diretamente com o modelo de objetos do Jenkins para eficiência e capacidade de solução de problemas incomparáveis.
Dominando o Console de Script Groovy do Jenkins para Administração Avançada de Sistemas
O Console de Script Groovy do Jenkins é útil para tarefas que não podem ser feitas de forma limpa pela interface do usuário: encontrar um build travado, verificar o estado do agente, inspecionar a configuração do job ou fazer uma alteração em lote cuidadosamente definida. Também é uma das maneiras mais fáceis de danificar um controlador Jenkins se você colar um script que não entende.
Trate o console como acesso root em um servidor de produção. Leia primeiro, imprima o que está prestes a alterar, teste em um controlador não produtivo quando possível, e só então escreva.
Entendendo o Console de Script do Jenkins
O Console de Script do Jenkins (Gerenciar Jenkins -> Console de Script) fornece acesso direto ao modelo de objetos do controlador Jenkins em execução usando Groovy. Você pode inspecionar jobs, builds, nós, visualizações, metadados de credenciais, estado de plugins e muitos outros objetos em tempo de execução.
Por que usar o Console de Script?
- Execução Imediata: Execute scripts instantaneamente sem esperar que um job seja acionado ou um pipeline seja iniciado.
- Depuração de Sistema: Acesse estado interno, logs e detalhes de configuração não expostos pela GUI.
- Operações em Lote: Modifique vários jobs, reconfigure agentes ou limpe dados antigos em toda a instância rapidamente.
- Prototipar Scripts: Teste a lógica Groovy antes de incorporá-la em bibliotecas compartilhadas ou pipelines declarativos.
Precaução de Segurança: O Poder do Acesso Direto
AVISO: Scripts executados no console são executados com privilégios administrativos completos no mestre Jenkins. Um script mal escrito pode corromper configurações, excluir builds ou travar a instância Jenkins. Sempre teste scripts complexos minuciosamente em um ambiente não produtivo primeiro.
Objetos Groovy Essenciais e Acesso à API
O poder do console vem do acesso direto aos objetos centrais do Jenkins. Esses objetos estão implicitamente disponíveis no ambiente de execução Groovy:
Jenkins.instance: O objeto singleton central do Jenkins, representando o controlador em execução.Hudson: Um alias paraJenkins.Jenkins.instance.getItemByFullName('JobName'): Acessa um job específico.Jenkins.instance.getComputer('AgentName'): Acessa um agente (nó) específico.
Acessando a Instância Jenkins
Para verificar se você tem acesso, o comando mais simples é imprimir a versão do Jenkins:
println "Versão do Jenkins: ${Jenkins.instance.version}"
println "Executando como usuário: ${Jenkins.instance.getAuthentication().getName()}"
Nas versões atuais do Jenkins, você pode ver exemplos usando Jenkins.get() em vez de Jenkins.instance. Ambos os padrões aparecem em scripts do mundo real. Para novos scripts, Jenkins.get() geralmente é mais claro:
import jenkins.model.Jenkins
def jenkins = Jenkins.get()
println "URL Raiz: ${jenkins.getRootUrl()}"
Scripts Administrativos Práticos
Aqui estão vários scripts acionáveis que demonstram controle administrativo avançado através do Console de Script.
1. Atualizando Configurações de Jobs em Lote
Este script itera por jobs Freestyle existentes e adiciona um sufixo à descrição. Observe o tratamento seguro para nulo; muitos jobs não têm descrição.
import hudson.model.FreeStyleProject
final String SUFIXO = " [Atualização Automatizada]"
def contagem = 0
Jenkins.instance.getAllItems(FreeStyleProject.class).each { job ->
def atual = job.getDescription() ?: ""
if (!atual.endsWith(SUFIXO)) {
job.setDescription(atual + SUFIXO)
job.save()
println "Descrição atualizada para: ${job.getName()}"
contagem++
}
}
println "\nFinalizado. Total de jobs atualizados: ${contagem}"
2. Gerenciando Agentes Jenkins (Nós)
Os administradores frequentemente precisam colocar agentes offline para manutenção ou desconectar manualmente nós com mau comportamento.
Desconectando um Agente Temporariamente
Este script desconecta um agente, impedindo que novos builds sejam iniciados nele, mas permitindo que builds em execução terminem.
import hudson.model.Computer
final String NOME_AGENTE = "meu-agente-especifico"
def agente = Jenkins.get().getComputer(NOME_AGENTE)
if (agente) {
// Colocar temporariamente offline
agente.setTemporarilyOffline(true, "Manutenção iniciada pelo Script Admin.")
println "Agente '${NOME_AGENTE}' definido como temporariamente offline."
} else {
println "Agente '${NOME_AGENTE}' não encontrado."
}
Forçando um Agente Offline e Desconectando Tarefas em Execução
Se um agente precisar ser desligado imediatamente, você pode forçá-lo offline e desconectar quaisquer builds em execução, o que os marcará como falhos ou abortados dependendo da configuração.
import hudson.model.Computer
final String NOME_AGENTE = "no-sem-resposta-01"
def agente = Jenkins.get().getComputer(NOME_AGENTE)
if (agente) {
// Forçar offline e desconectar tarefas em execução imediatamente
agente.doDoDisconnect()
println "Agente '${NOME_AGENTE}' desconectado à força."
} else {
println "Agente '${NOME_AGENTE}' não encontrado."
}
3. Manipulando Builds em Execução
Quando um build crítico trava ou precisa de cancelamento imediato, o Console de Script fornece o caminho mais rápido.
Abortando um Build Específico em Execução
Para abortar um build identificado pelo seu caminho completo (por exemplo, PipelineJob/BuildNumber):
// Exemplo: Abortando o build #5 do job chamado 'DeployCritico'
final String NOME_JOB = "DeployCritico"
final int NUMERO_BUILD = 5
def job = Jenkins.get().getItemByFullName(NOME_JOB)
def build = job?.getBuild(NUMERO_BUILD)
if (build && build.isBuilding()) {
build.doCancel()
println "Build ${NOME_JOB}#${NUMERO_BUILD} foi cancelado."
} else {
println "Build ${NOME_JOB}#${NUMERO_BUILD} não está em execução ou não existe."
}
4. Limpando Registros de Build Antigos
Gerenciar espaço em disco frequentemente requer a poda agressiva de builds antigos. Este script identifica e exclui todos os builds mais antigos que 30 dias para um job especificado.
import hudson.model.Job
import java.util.concurrent.TimeUnit
final String JOB_ALVO = "JobArquivamentoLegado"
final int DIAS_MANTER = 30
def job = Jenkins.get().getItemByFullName(JOB_ALVO)
if (job instanceof Job) {
long tempoCorte = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(DIAS_MANTER)
int contagemExcluidos = 0
job.getBuilds().each { build ->
if (build.getTimeInMillis() < tempoCorte) {
println "Excluindo build antigo: ${build.getDisplayName()}"
build.delete()
contagemExcluidos++
}
}
println "\nLimpeza concluída. Excluídos ${contagemExcluidos} builds para ${JOB_ALVO}."
} else {
println "Job '${JOB_ALVO}' não encontrado ou não é um tipo de Job padrão."
}
Melhores Práticas para Scripts no Console
Ao realizar alterações em nível de sistema, siga estas melhores práticas para manter a estabilidade:
- Use
.save(): Sempre que modificar um objeto de configuração (como um Job ou View), você deve chamar.save()nesse objeto para que a alteração persista após a reinicialização do Jenkins. As configurações são mantidas apenas na memória até serem salvas. - Verifique a Existência do Objeto: Sempre envolva chamadas de API com verificações (
if (objeto)outry-catch) para evitar que o console trave se você digitar incorretamente o nome de um job ou agente. - Evite Loops Persistentes: Os scripts são executados de forma síncrona. Não execute loops ou processos de longa duração diretamente no console, a menos que tenha certeza de que serão concluídos rapidamente, pois isso bloqueia a interface do console.
- Aproveite Métodos Integrados: Os objetos Groovy do Jenkins geralmente possuem métodos auxiliares específicos (como
doCancel()oudoDoDisconnect()). Use-os em vez de tentar manipular manualmente o estado interno sempre que possível. - Use o Modo Silencioso (se aplicável): Ao realizar operações em lote que geram atualizações excessivas de status de build, considere se desabilitar temporariamente os recursos de notificação de eventos é justificado, embora isso geralmente exija acesso mais profundo ao sistema do que a administração padrão.
Padrão de Simulação Mais Seguro
Para qualquer alteração em lote, adicione um sinalizador de simulação primeiro:
import jenkins.model.Jenkins
import hudson.model.Job
final boolean SIMULACAO = true
final String CORRESPONDENCIA = "legado-"
Jenkins.get().getAllItems(Job.class).findAll { job ->
job.fullName.contains(CORRESPONDENCIA)
}.each { job ->
println "${SIMULACAO ? 'Atualizaria' : 'Atualizando'} ${job.fullName}"
if (!SIMULACAO) {
job.setDescription((job.getDescription() ?: "") + "\nRevisado durante a limpeza.")
job.save()
}
}
Execute uma vez com SIMULACAO = true, copie a saída para o seu ticket de alteração e só então execute com false. Esse pequeno hábito evita a maioria das alterações amplas acidentais.
Lendo a Configuração do Job Sem Alterá-la
Às vezes, o console é melhor usado como uma ferramenta de pesquisa. Por exemplo, para encontrar jobs Pipeline que ainda referenciam um host Git antigo:
import jenkins.model.Jenkins
import org.jenkinsci.plugins.workflow.job.WorkflowJob
final String AGULHA = "git.old.example.com"
Jenkins.get().getAllItems(WorkflowJob.class).each { job ->
def definicao = job.getDefinition()
def texto = definicao?.getScript()
if (texto?.contains(AGULHA)) {
println "Encontrado ${AGULHA} em ${job.fullName}"
}
}
Este exemplo funciona apenas para scripts Pipeline embutidos. Se o job usar Jenkinsfile do SCM, o Jenkins armazena a definição do SCM em vez do conteúdo do arquivo. Essa distinção é importante: o console pode inspecionar a configuração do Jenkins, mas não pode ler magicamente todos os branches de todos os repositórios remotos, a menos que seu script faça isso explicitamente.
Encontrando Builds Travados Sem Adivinhar
Durante um incidente, a primeira pergunta é frequentemente "o que está sendo executado agora?". Este script imprime builds em execução com sua duração e executor:
import jenkins.model.Jenkins
Jenkins.get().getComputers().each { computador ->
computador.executors.each { executor ->
def executavel = executor.currentExecutable
if (executavel) {
def build = executavel
println "${computador.displayName} :: ${build.fullDisplayName} :: ${build.durationString}"
}
}
}
Use isso como um script de inspeção primeiro. Se precisar abortar algo, mire em um build conhecido em vez de cancelar tudo que parece antigo. Migrações de banco de dados de longa duração, jobs de lançamento e pipelines de aprovação manual podem parecer "travados" de fora.
Para jobs Pipeline, você também pode inspecionar se um build está pausado para entrada:
import jenkins.model.Jenkins
import org.jenkinsci.plugins.workflow.job.WorkflowRun
import org.jenkinsci.plugins.workflow.support.steps.input.InputAction
Jenkins.get().getAllItems().each { job ->
job.builds?.findAll { it instanceof WorkflowRun && it.isBuilding() }?.each { execucao ->
def entrada = execucao.getAction(InputAction)
if (entrada) {
println "Aguardando entrada: ${execucao.fullDisplayName}"
}
}
}
Isso evita um erro comum: abortar uma implantação que está intencionalmente aguardando aprovação.
Inspeção de Plugins e Versões
O console é útil quando a interface do usuário está lenta ou você precisa de um inventário rápido. Isso imprime plugins instalados e versões:
import jenkins.model.Jenkins
Jenkins.get().pluginManager.plugins
.sort { it.shortName }
.each { plugin ->
println "${plugin.shortName}:${plugin.version}"
}
Não use o Console de Script como substituto para um processo gerenciado de atualização de plugins. As atualizações de plugins podem afetar o carregamento de jobs, o comportamento do Pipeline, as ligações de credenciais e as conexões de agentes. O console é melhor para inspeção, diagnóstico de emergência ou pequenos reparos direcionados.
Faça Backup Antes de Scripts de Escrita
Antes de executar qualquer script que chame .save(), exclua builds, desconecte agentes ou altere definições de jobs, certifique-se de ter um backup atual de $JENKINS_HOME ou da fonte de configuração gerenciada do seu controlador. Se sua instância Jenkins for configurada por JCasC, Job DSL, valores Helm ou outro sistema baseado em Git, lembre-se de que uma edição no console pode ser sobrescrita pela próxima reconciliação.
Nesses ambientes, use o console para confirmar o problema e, em seguida, corrija a fonte da verdade. Uma correção apenas no console é aceitável para uma emergência, mas registre-a para que a configuração durável possa ser atualizada posteriormente.
Acesso Remoto ao Console de Script
Muitos administradores conhecem o console do navegador, mas o Jenkins também pode executar Groovy através da CLI quando esse acesso está habilitado e permitido:
java -jar jenkins-cli.jar -s https://jenkins.example.com/ groovy = < script.groovy
Isso é útil para scripts revisados porque você pode manter o arquivo Groovy no controle de versão, submetê-lo à revisão por pares e executar o conteúdo exato que foi aprovado. Também torna a saída mais fácil de capturar em um ticket de incidente.
Não habilite a CLI ou a execução remota de scripts casualmente. A permissão necessária para acesso ao Console de Script é altamente privilegiada. Limite-a a administradores confiáveis, use registro de auditoria quando disponível e prefira sessões administrativas de curta duração. Se sua organização usa controle de acesso baseado em funções, verifique quem realmente tem direitos Overall/Administer ou equivalentes antes de assumir que o console está bloqueado.
Para manutenção repetível, um job Jenkins que executa um script revisado sob parâmetros controlados é muitas vezes melhor do que o trabalho ad hoc no console do navegador. O console continua sendo a ferramenta de emergência; a automação controlada por versão deve lidar com as tarefas que você espera repetir.
Antes de executar um script remoto, imprima a URL do Jenkins e o nome de autenticação atual no topo da saída. Parece básico, mas pega o pior erro: executar um reparo de produção contra o controlador errado ou sob a conta errada.
import jenkins.model.Jenkins
def j = Jenkins.get()
println "Controlador: ${j.getRootUrl()}"
println "Usuário: ${j.getAuthentication().getName()}"
O Que Não Colocar no Console
Evite scripts que dormem por muito tempo, fazem polling para sempre, baixam grandes arquivos remotos ou realizam exclusão ampla de sistema de arquivos. O console é executado dentro do processo do controlador. Se o script queimar CPU, bloquear threads ou encher a memória, afeta o próprio sistema de CI.
Evite também imprimir segredos. Os objetos de credenciais do Jenkins são intencionalmente protegidos, mas os administradores ainda podem escrever scripts que exponham material sensível. Se você precisar auditar credenciais, imprima IDs, descrições, domínios e referências de uso. Não imprima valores secretos no navegador, logs de build ou chat.
Os melhores scripts de console são curtos, chatos e reversíveis. Use-os para inspecionar o estado, realizar um reparo estreito ou automatizar uma tarefa administrativa conhecida. Quando um script se tornar longo o suficiente para precisar de testes, mova-o para um repositório de administração compartilhado ou um job de gerenciamento Jenkins onde possa ser revisado como código normal.