web-dev-qa-db-fra.com

Comment puis-je obtenir la sortie d'une commande Shell exécutée à l'aide d'une variable de Jenkinsfile (groovy)?

J'ai quelque chose comme ceci sur un Jenkinsfile (Groovy) et je veux enregistrer le stdout et le code de sortie dans une variable afin d'utiliser l'information plus tard.

sh "ls -l"

Comment puis-je faire cela, d'autant plus qu'il semble que vous ne pouvez pas exécuter de code groovy à l'intérieur de la Jenkinsfile?

165
sorin

La dernière version de l'étape de pipeline sh vous permet d'effectuer les opérations suivantes:

// 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}"

Une autre caractéristique est l'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}"

Ces options ont été ajoutées en fonction de this issue.

Voir official documentation pour la commande sh.

296
G. Roggemans

réponse rapide est la suivante:

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

Je pense qu'il existe une demande de fonctionnalité pour pouvoir obtenir le résultat de l'étape sh, mais pour autant que je sache, il n'y a actuellement aucune autre option.

EDIT: JENKINS-261

EDIT2: Pas vraiment sûr depuis quelle version, mais les étapes sh/bat peuvent maintenant renvoyer la sortie std, simplement:

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

La version actuelle du pipeline prend en charge nativement returnStdout et returnStatus, ce qui permet d'obtenir une sortie ou un statut à partir de sh/bat étapes.

Un exemple:

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

Un officiel documentation .

36
luka5z

c'est un exemple de cas, ce qui aura un sens, je crois!

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

Si vous voulez obtenir le stdout ET savoir si la commande a réussi ou non, utilisez simplement returnStdout et enveloppez-la dans un gestionnaire d'exceptions:

pipeline scripté

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}")
}

sortie :

[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

Malheureusement, il manque à hudson.AbortException toute méthode utile pour obtenir cet état de sortie. Par conséquent, si la valeur réelle est requise, vous devez l’analyser dans le message (ugh!).

Contrairement à la Javadoc https://javadoc.jenkins-ci.org/hudson/AbortException.html la construction n’est pas pas a échoué lorsque cette exception est interceptée. Il échoue quand il est pas attrapé!

Mise à jour: Si vous souhaitez également la sortie STDERR de la commande Shell, plusieurs approches sont possibles:

a) Redirigez STDERR vers STDOUT 2>&1 - mais vous devez ensuite analyser cela hors de la sortie principale et vous n'obtiendrez pas la sortie si la commande échoue - car vous êtes dans le gestionnaire d'exceptions.

b) redirigez STDERR vers un fichier temporaire (le nom que vous avez préparé précédemment) 2>filename (mais n'oubliez pas de nettoyer le fichier ultérieurement) - c'est-à-dire. le code principal devient:

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) Allez dans l'autre sens, définissez plutôt returnStatus=true, supprimez le gestionnaire d'exceptions et capturez toujours la sortie dans un fichier, c'est-à-dire:

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
}

Avertissement: le code ci-dessus est spécifique à Unix/Linux - Windows requiert des commandes Shell complètement différentes.

9
Ed Randall