web-dev-qa-db-ger.com

Wie kann ich die Ausgabe eines Shell-Befehls mit in eine Variable von Jenkinsfile (groovy) ausführen lassen?

Ich habe so etwas auf einem Jenkinsfile (Groovy) und ich möchte die stdout und den Exit-Code in einer Variablen aufzeichnen, um die Informationen später zu verwenden.

sh "ls -l"

Wie kann ich das tun, zumal es den Anschein hat, dass Sie in Jenkinsfile keinen wirklich fetzigen Code ausführen können?

165
sorin

Mit der neuesten Version des Pipeline-Schritts sh können Sie Folgendes tun:

// Git committer email
GIT_COMMIT_EMAIL = sh (
    script: 'git --no-pager show -s --format=\'%ae\'',
    returnStdout: true
).trim()
echo "Git committer email: ${GIT_COMMIT_EMAIL}"

Eine weitere Funktion ist die Option returnStatus.

// Test commit message for flags
BUILD_FULL = sh (
    script: "git log -1 --pretty=%B | grep '\\[jenkins-full]'",
    returnStatus: true
) == 0
echo "Build full flag: ${BUILD_FULL}"

Diese Optionen wurden basierend auf this Problem hinzugefügt.

Siehe official documentation für den Befehl sh.

296
G. Roggemans

die schnelle Antwort lautet:

sh "ls -l > commandResult"
result = readFile('commandResult').trim()

Ich denke, es gibt eine Feature-Anfrage, um das Ergebnis von sh step zu erhalten, aber meines Wissens gibt es derzeit keine andere Option.

BEARBEITEN: JENKINS-261

EDIT2: Nicht ganz sicher, seit welcher Version, aber sh/bat Schritte können jetzt die Standardausgabe zurückgeben, einfach:

def output = sh returnStdout: true, script: 'ls -l'
38
vehovmar

Die aktuelle Pipeline-Version unterstützt nativ returnStdout und returnStatus, wodurch die Ausgabe oder der Status von sh/bat Schritten abgerufen werden kann.

Ein Beispiel:

def ret = sh(script: 'uname', returnStdout: true)
println ret

Eine offizielle Dokumentation .

36
luka5z

dies ist ein Beispielfall, der meiner Meinung nach Sinn ergibt!

node('master'){
    stage('stage1'){
    def commit = sh (returnStdout: true, script: '''echo hi
    echo bye | grep -o "e"
    date
    echo lol''').split()


    echo "${commit[-1]} "

    }
}
10
Bibek Mantree

Wenn Sie die stdout erhalten möchten UND wissen möchten, ob der Befehl erfolgreich war oder nicht, verwenden Sie einfach returnStdout und schließen Sie ihn in einen Ausnahmehandler ein:

Skript-Pipeline

try {
    // Fails with non-zero exit if dir1 does not exist
    def dir1 = sh(script:'ls -la dir1', returnStdout:true).trim()
} catch (Exception ex) {
    println("Unable to read dir1: ${ex}")
}

Ausgabe :

[Pipeline] sh
[Test-Pipeline] Running Shell script
+ ls -la dir1
ls: cannot access dir1: No such file or directory
[Pipeline] echo
unable to read dir1: hudson.AbortException: script returned exit code 2

Leider fehlt in hudson.AbortException eine nützliche Methode, um diesen Exit-Status zu erhalten. Wenn also der tatsächliche Wert erforderlich ist, müssen Sie ihn aus der Nachricht auslesen (ugh!).

Im Gegensatz zum Javadoc https://javadoc.jenkins-ci.org/hudson/AbortException.html ist der Build nicht ist fehlgeschlagen, wenn diese Ausnahme abgefangen wird. Es schlägt fehl, wenn es nicht abgefangen wird!

Update: Wenn Sie auch die STDERR-Ausgabe des Shell-Befehls wünschen, gibt es einige mögliche Ansätze:

a) Leiten Sie STDERR zu STDOUT 2>&1 um - aber es liegt dann an Ihnen, dies aus der Hauptausgabe zu analysieren, und Sie werden die Ausgabe nicht erhalten, wenn der Befehl fehlschlägt - weil Sie sich im Ausnahmehandler befinden.

b) leiten Sie STDERR in eine temporäre Datei um (deren Namen Sie zuvor vorbereitet haben) 2>filename (aber denken Sie daran, die Datei danach zu bereinigen) - dh. Hauptcode wird:

def stderrfile = 'stderr.out'
try {
    def dir1 = sh(script:"ls -la dir1 2>${stderrfile}", returnStdout:true).trim()
} catch (Exception ex) {
    def errmsg = readFile(stderrfile)
    println("Unable to read dir1: ${ex} - ${errmsg}")
}

c) Gehen Sie in die andere Richtung, setzen Sie stattdessen returnStatus=true, verzichten Sie auf den Ausnahmehandler und erfassen Sie die Ausgabe immer in einer Datei, dh:

def outfile = 'stdout.out'
def status = sh(script:"ls -la dir1 >${outfile} 2>&1", returnStatus:true)
def output = readFile(outfile).trim()
if (status == 0) {
    // output is directory listing from stdout
} else {
    // output is error message from stderr
}

Warnung: Der obige Code ist Unix/Linux-spezifisch - Windows benötigt völlig andere Shell-Befehle.

9
Ed Randall