Beherrschung der Jenkins Groovy Script Console für fortgeschrittene Systemadministration
Entfesseln Sie die versteckte Leistungsfähigkeit der Jenkins-Administration mit der Groovy Script Console. Dieser umfassende Leitfaden bietet fachkundige, umsetzbare Groovy-Skripte für Systemadministratoren, um komplexe Aufgaben sofort auszuführen, wie z. B. Bulk-Konfigurationsaktualisierungen, sofortige Agentenverwaltung (Trennen/Wiederverbinden) und erzwungenes Abbrechen laufender Builds. Erfahren Sie, wie Sie direkt mit dem Jenkins-Objektmodell interagieren, um beispiellose Effizienz und Fehlerbehebungsfähigkeiten zu erlangen.
Beherrschung der Jenkins Groovy Script Console für fortgeschrittene Systemadministration
Die Jenkins Groovy Script Console ist nützlich für Aufgaben, die Sie nicht sauber über die Benutzeroberfläche erledigen können: einen feststeckenden Build finden, den Agentenstatus überprüfen, die Jobkonfiguration inspizieren oder eine sorgfältig abgegrenzte Bulk-Änderung vornehmen. Sie ist auch eine der einfachsten Möglichkeiten, einen Jenkins-Controller zu beschädigen, wenn Sie ein Skript einfügen, das Sie nicht verstehen.
Behandeln Sie die Konsole wie Root-Zugriff auf einem Produktionsserver. Lesen Sie zuerst, drucken Sie, was Sie ändern möchten, testen Sie nach Möglichkeit auf einem Nicht-Produktions-Controller und schreiben Sie erst dann.
Verständnis der Jenkins Script Console
Die Jenkins Script Console (Jenkins verwalten -> Script Console) bietet direkten Zugriff auf das Objektmodell des laufenden Jenkins-Controllers mit Groovy. Sie können Jobs, Builds, Nodes, Ansichten, Metadaten von Anmeldeinformationen, Plugin-Status und viele andere Laufzeitobjekte inspizieren.
Warum die Script Console verwenden?
- Sofortige Ausführung: Führen Sie Skripte sofort aus, ohne auf einen Job-Trigger oder den Start einer Pipeline zu warten.
- System-Debugging: Greifen Sie auf internen Zustand, Logs und Konfigurationsdetails zu, die nicht über die GUI verfügbar sind.
- Bulk-Operationen: Ändern Sie mehrere Jobs schnell, konfigurieren Sie Agenten neu oder löschen Sie alte Daten über die gesamte Instanz.
- Prototyp-Skripte: Testen Sie Groovy-Logik, bevor Sie sie in Shared Libraries oder deklarative Pipelines einbetten.
Sicherheitsvorkehrung: Die Macht des direkten Zugriffs
WARNUNG: In der Konsole ausgeführte Skripte werden mit vollen Administratorrechten auf dem Jenkins-Master ausgeführt. Ein schlecht geschriebenes Skript kann Konfigurationen beschädigen, Builds löschen oder die Jenkins-Instanz zum Absturz bringen. Testen Sie komplexe Skripte immer gründlich zuerst in einer Nicht-Produktionsumgebung.
Wesentliche Groovy-Objekte und API-Zugriff
Die Stärke der Konsole liegt im direkten Zugriff auf die Kern-Jenkins-Objekte. Diese Objekte sind innerhalb der Groovy-Ausführungsumgebung implizit verfügbar:
Jenkins.instance: Das zentrale Jenkins-Singleton-Objekt, das den laufenden Controller repräsentiert.Hudson: Ein Alias fürJenkins.Jenkins.instance.getItemByFullName('JobName'): Greift auf einen bestimmten Job zu.Jenkins.instance.getComputer('AgentName'): Greift auf einen bestimmten Agenten (Node) zu.
Zugriff auf die Jenkins-Instanz
Um zu überprüfen, ob Sie Zugriff haben, ist der einfachste Befehl, die Jenkins-Version auszugeben:
println "Jenkins Version: ${Jenkins.instance.version}"
println "Ausgeführt als Benutzer: ${Jenkins.instance.getAuthentication().getName()}"
In aktuellen Jenkins-Versionen sehen Sie möglicherweise Beispiele, die Jenkins.get() anstelle von Jenkins.instance verwenden. Beide Muster kommen in realen Skripten vor. Für neue Skripte ist Jenkins.get() normalerweise klarer:
import jenkins.model.Jenkins
def jenkins = Jenkins.get()
println "Root-URL: ${jenkins.getRootUrl()}"
Praktische Administrationsskripte
Hier sind mehrere umsetzbare Skripte, die fortgeschrittene administrative Kontrolle über die Script Console demonstrieren.
1. Bulk-Aktualisierung von Job-Konfigurationen
Dieses Skript durchläuft vorhandene Freestyle-Jobs und fügt der Beschreibung ein Suffix hinzu. Beachten Sie die nullsichere Handhabung; viele Jobs haben keine Beschreibung.
import hudson.model.FreeStyleProject
final String SUFFIX = " [Automatisiertes Update]"
def count = 0
Jenkins.instance.getAllItems(FreeStyleProject.class).each { job ->
def current = job.getDescription() ?: ""
if (!current.endsWith(SUFFIX)) {
job.setDescription(current + SUFFIX)
job.save()
println "Beschreibung aktualisiert für: ${job.getName()}"
count++
}
}
println "\nFertig. Insgesamt aktualisierte Jobs: ${count}"
2. Verwalten von Jenkins-Agenten (Nodes)
Administratoren müssen Agenten oft für Wartungsarbeiten offline nehmen oder fehlerhafte Nodes manuell trennen.
Vorübergehendes Trennen eines Agenten
Dieses Skript trennt einen Agenten, verhindert, dass neue Builds darauf starten, erlaubt aber laufenden Builds, zu Ende zu laufen.
import hudson.model.Computer
final String AGENT_NAME = "mein-spezifischer-agent"
def agent = Jenkins.get().getComputer(AGENT_NAME)
if (agent) {
// Vorübergehend offline setzen
agent.setTemporarilyOffline(true, "Wartung gestartet durch Admin-Skript.")
println "Agent '${AGENT_NAME}' wurde vorübergehend offline gesetzt."
} else {
println "Agent '${AGENT_NAME}' nicht gefunden."
}
Erzwungenes Offline-Schalten eines Agenten und Trennen laufender Aufgaben
Wenn ein Agent sofort heruntergefahren werden muss, können Sie ihn zwangsweise offline schalten und alle laufenden Builds trennen, was sie je nach Konfiguration als fehlgeschlagen oder abgebrochen markiert.
import hudson.model.Computer
final String AGENT_NAME = "nicht-reagierender-node-01"
def agent = Jenkins.get().getComputer(AGENT_NAME)
if (agent) {
// Zwangsweise offline schalten und laufende Aufgaben sofort trennen
agent.doDoDisconnect()
println "Agent '${AGENT_NAME}' wurde zwangsweise getrennt."
} else {
println "Agent '${AGENT_NAME}' nicht gefunden."
}
3. Manipulieren laufender Builds
Wenn ein kritischer Build hängt oder sofort abgebrochen werden muss, bietet die Script Console den schnellsten Weg.
Abbrechen eines bestimmten laufenden Builds
Um einen Build abzubrechen, der durch seinen vollständigen Pfad identifiziert wird (z. B. PipelineJob/BuildNumber):
// Beispiel: Abbruch von Build #5 des Jobs namens 'CriticalDeploy'
final String JOB_NAME = "CriticalDeploy"
final int BUILD_NUMBER = 5
def job = Jenkins.get().getItemByFullName(JOB_NAME)
def build = job?.getBuild(BUILD_NUMBER)
if (build && build.isBuilding()) {
build.doCancel()
println "Build ${JOB_NAME}#${BUILD_NUMBER} wurde abgebrochen."
} else {
println "Build ${JOB_NAME}#${BUILD_NUMBER} läuft nicht oder existiert nicht."
}
4. Bereinigen alter Build-Aufzeichnungen
Die Verwaltung des Speicherplatzes erfordert oft das aggressive Entfernen alter Builds. Dieses Skript identifiziert und löscht alle Builds, die älter als 30 Tage für einen bestimmten Job sind.
import hudson.model.Job
import java.util.concurrent.TimeUnit
final String TARGET_JOB = "LegacyArchivingJob"
final int DAYS_TO_KEEP = 30
def job = Jenkins.get().getItemByFullName(TARGET_JOB)
if (job instanceof Job) {
long cutoffTime = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(DAYS_TO_KEEP)
int deletedCount = 0
job.getBuilds().each { build ->
if (build.getTimeInMillis() < cutoffTime) {
println "Lösche alten Build: ${build.getDisplayName()}"
build.delete()
deletedCount++
}
}
println "\nBereinigung abgeschlossen. ${deletedCount} Builds für ${TARGET_JOB} gelöscht."
} else {
println "Job '${TARGET_JOB}' nicht gefunden oder ist kein Standard-Job-Typ."
}
Best Practices für das Scripting in der Konsole
Wenn Sie systemweite Änderungen vornehmen, halten Sie sich an diese Best Practices, um die Stabilität zu gewährleisten:
- Verwenden Sie
.save(): Wenn Sie ein Konfigurationsobjekt (wie einen Job oder eine Ansicht) ändern, müssen Sie.save()für dieses Objekt aufrufen, damit die Änderung nach einem Jenkins-Neustart bestehen bleibt. Konfigurationen werden nur im Speicher gehalten, bis sie gespeichert werden. - Überprüfen Sie die Existenz von Objekten: Umwickeln Sie API-Aufrufe immer mit Überprüfungen (
if (object)odertry-catch), um zu verhindern, dass die Konsole abstürzt, wenn Sie einen Job- oder Agentennamen falsch eingeben. - Vermeiden Sie persistente Schleifen: Skripte werden synchron ausgeführt. Führen Sie keine lang laufenden Schleifen oder Prozesse direkt in der Konsole aus, es sei denn, Sie sind sicher, dass sie schnell abgeschlossen werden, da dies die Konsolen-Benutzeroberfläche blockiert.
- Nutzen Sie integrierte Methoden: Jenkins Groovy-Objekte haben oft spezifische Hilfsmethoden (wie
doCancel()oderdoDoDisconnect()). Verwenden Sie diese, anstatt zu versuchen, den internen Zustand manuell zu manipulieren, wo immer möglich. - Verwenden Sie den Ruhemodus (falls zutreffend): Wenn Sie Bulk-Operationen durchführen, die übermäßige Build-Status-Updates erzeugen, überlegen Sie, ob die vorübergehende Deaktivierung von Ereignisbenachrichtigungsfunktionen gerechtfertigt ist, obwohl dies normalerweise einen tieferen Systemzugriff als die Standardadministration erfordert.
Sichereres Trockenlauf-Muster
Fügen Sie für jede Bulk-Änderung zuerst ein Trockenlauf-Flag hinzu:
import jenkins.model.Jenkins
import hudson.model.Job
final boolean DRY_RUN = true
final String MATCH = "legacy-"
Jenkins.get().getAllItems(Job.class).findAll { job ->
job.fullName.contains(MATCH)
}.each { job ->
println "${DRY_RUN ? 'Würde aktualisieren' : 'Aktualisiere'} ${job.fullName}"
if (!DRY_RUN) {
job.setDescription((job.getDescription() ?: "") + "\nÜberprüft während der Bereinigung.")
job.save()
}
}
Führen Sie es einmal mit DRY_RUN = true aus, kopieren Sie die Ausgabe in Ihr Änderungsticket und führen Sie es erst dann mit false aus. Diese kleine Gewohnheit verhindert die meisten versehentlichen weitreichenden Änderungen.
Lesen der Job-Konfiguration ohne Änderung
Manchmal wird die Konsole am besten als Suchwerkzeug verwendet. Zum Beispiel, um Pipeline-Jobs zu finden, die noch einen alten Git-Host referenzieren:
import jenkins.model.Jenkins
import org.jenkinsci.plugins.workflow.job.WorkflowJob
final String NEEDLE = "git.old.example.com"
Jenkins.get().getAllItems(WorkflowJob.class).each { job ->
def definition = job.getDefinition()
def text = definition?.getScript()
if (text?.contains(NEEDLE)) {
println "Gefunden ${NEEDLE} in ${job.fullName}"
}
}
Dieses Beispiel funktioniert nur für Inline-Pipeline-Skripte. Wenn der Job Jenkinsfile aus SCM verwendet, speichert Jenkins die SCM-Definition und nicht den Dateiinhalt. Diese Unterscheidung ist wichtig: Die Konsole kann die Jenkins-Konfiguration inspizieren, aber sie kann nicht magisch jeden Branch jedes entfernten Repositorys lesen, es sei denn, Ihr Skript tut dies explizit.
Finden feststeckender Builds ohne Raten
Während eines Vorfalls ist die erste Frage oft: "Was läuft gerade?" Dieses Skript druckt laufende Builds mit ihrer Dauer und ihrem Executor:
import jenkins.model.Jenkins
Jenkins.get().getComputers().each { computer ->
computer.executors.each { executor ->
def executable = executor.currentExecutable
if (executable) {
def build = executable
println "${computer.displayName} :: ${build.fullDisplayName} :: ${build.durationString}"
}
}
}
Verwenden Sie dies zuerst als Inspektionsskript. Wenn Sie etwas abbrechen müssen, zielen Sie auf einen bekannten Build, anstatt alles abzubrechen, was alt aussieht. Lang laufende Datenbankmigrationen, Release-Jobs und manuelle Genehmigungs-Pipelines können von außen "feststeckend" aussehen.
Für Pipeline-Jobs können Sie auch überprüfen, ob ein Build auf Eingabe wartet:
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 { run ->
def input = run.getAction(InputAction)
if (input) {
println "Warte auf Eingabe: ${run.fullDisplayName}"
}
}
}
Das verhindert einen häufigen Fehler: das Abbrechen einer Bereitstellung, die absichtlich auf Genehmigung wartet.
Plugin- und Versionsinspektion
Die Konsole ist praktisch, wenn die Benutzeroberfläche langsam ist oder Sie eine schnelle Bestandsaufnahme benötigen. Dies druckt installierte Plugins und Versionen:
import jenkins.model.Jenkins
Jenkins.get().pluginManager.plugins
.sort { it.shortName }
.each { plugin ->
println "${plugin.shortName}:${plugin.version}"
}
Verwenden Sie die Script Console nicht als Ersatz für einen verwalteten Plugin-Update-Prozess. Plugin-Upgrades können das Laden von Jobs, das Pipeline-Verhalten, Anmeldeinformationsbindungen und Agentenverbindungen beeinträchtigen. Die Konsole ist am besten für Inspektion, Notfalldiagnose oder kleine gezielte Reparaturen geeignet.
Sichern Sie vor Schreibskripten
Bevor Sie ein Skript ausführen, das .save() aufruft, Builds löscht, Agenten trennt oder Jobdefinitionen ändert, stellen Sie sicher, dass Sie ein aktuelles Backup von $JENKINS_HOME oder der verwalteten Konfigurationsquelle Ihres Controllers haben. Wenn Ihre Jenkins-Instanz durch JCasC, Job DSL, Helm-Werte oder ein anderes Git-gestütztes System konfiguriert ist, denken Sie daran, dass eine Konsolenbearbeitung durch die nächste Abstimmung überschrieben werden kann.
Verwenden Sie in diesen Umgebungen die Konsole, um das Problem zu bestätigen, und korrigieren Sie dann die Quelle der Wahrheit. Eine reine Konsolenlösung ist für einen Notfall akzeptabel, aber dokumentieren Sie sie, damit die dauerhafte Konfiguration danach aktualisiert werden kann.
Fernzugriff auf die Script Console
Viele Administratoren kennen die Browser-Konsole, aber Jenkins kann Groovy auch über die CLI ausführen, wenn dieser Zugriff aktiviert und erlaubt ist:
java -jar jenkins-cli.jar -s https://jenkins.example.com/ groovy = < script.groovy
Das ist nützlich für überprüfte Skripte, da Sie die Groovy-Datei in der Versionskontrolle behalten, sie durch Peer-Review laufen lassen und den genauen Inhalt ausführen können, der genehmigt wurde. Es macht es auch einfacher, die Ausgabe in einem Vorfallticket zu erfassen.
Aktivieren Sie CLI oder Remote-Skriptausführung nicht leichtfertig. Die für den Script Console-Zugriff erforderliche Berechtigung ist hochprivilegiert. Beschränken Sie sie auf vertrauenswürdige Administratoren, verwenden Sie, wo verfügbar, Audit-Logs und bevorzugen Sie kurzlebige Administrationssitzungen. Wenn Ihre Organisation eine rollenbasierte Zugriffskontrolle verwendet, überprüfen Sie, wer tatsächlich Overall/Administer oder gleichwertige Rechte hat, bevor Sie annehmen, dass die Konsole gesperrt ist.
Für wiederholbare Wartung ist ein Jenkins-Job, der ein überprüftes Skript unter kontrollierten Parametern ausführt, oft besser als Ad-hoc-Browser-Konsolenarbeit. Die Konsole bleibt das Notfallwerkzeug; die versionskontrollierte Automatisierung sollte die Aufgaben übernehmen, die Sie voraussichtlich wiederholen werden.
Bevor Sie ein Remote-Skript ausführen, drucken Sie die Jenkins-URL und den aktuellen Authentifizierungsnamen oben in der Ausgabe. Es klingt einfach, aber es fängt den schlimmsten Fehler ein: Ausführen einer Produktionsreparatur gegen den falschen Controller oder unter dem falschen Konto.
import jenkins.model.Jenkins
def j = Jenkins.get()
println "Controller: ${j.getRootUrl()}"
println "Benutzer: ${j.getAuthentication().getName()}"
Was Sie nicht in die Konsole setzen sollten
Vermeiden Sie Skripte, die lange schlafen, ewig abfragen, große entfernte Dateien herunterladen oder breite Dateisystemlöschungen durchführen. Die Konsole läuft innerhalb des Controller-Prozesses. Wenn das Skript CPU verbraucht, Threads blockiert oder den Speicher füllt, beeinträchtigt es das CI-System selbst.
Vermeiden Sie auch das Drucken von Geheimnissen. Jenkins-Anmeldeinformationsobjekte sind absichtlich geschützt, aber Administratoren können dennoch Skripte schreiben, die sensibles Material offenlegen. Wenn Sie Anmeldeinformationen prüfen müssen, drucken Sie IDs, Beschreibungen, Domänen und Verwendungsreferenzen. Drucken Sie keine geheimen Werte in den Browser, Build-Logs oder Chat.
Die besten Konsolenskripte sind kurz, langweilig und umkehrbar. Verwenden Sie sie, um den Zustand zu inspizieren, eine enge Reparatur durchzuführen oder eine bekannte administrative Aufgabe zu automatisieren. Wenn ein Skript lang genug wird, um Tests zu benötigen, verschieben Sie es in ein gemeinsames Admin-Repository oder einen Jenkins-Verwaltungsjob, wo es wie normaler Code überprüft werden kann.