358 votes

Comment obtenir la sortie d'une commande shell exécutée en utilisant dans une variable de Jenkinsfile (groovy) ?

J'ai quelque chose comme ça dans un fichier Jenkins (Groovy) et je veux enregistrer le stdout et le code de sortie dans une variable afin d'utiliser ces informations plus tard.

sh "ls -l"

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

3 votes

0 votes

617voto

G. Roggemans Points 2131

La dernière version du 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 le returnStatus opción.

// 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 sur la base de este question.

Voir officiel documentation para el sh commandement.

Pour les pipelines déclaratifs (voir les commentaires), il faut envelopper le code dans des script étape :

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

13 votes

On dirait que maintenant c'est documenté -> jenkins.io/doc/pipeline/steps/workflow-durable-task-step/

0 votes

Cela ne fonctionne pas pour moi avec le préfixe "vars". Lorsque j'utilise simplement GIT_COMMIT_EMAIL comme nom de var sans le préfixe, tout va bien.

0 votes

91voto

luka5z Points 3430

La version actuelle de Pipeline supporte nativement returnStdout y returnStatus qui permettent d'obtenir une sortie ou un statut de la part des services suivants sh / bat étapes.

Un exemple :

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

Un fonctionnaire documentation .

0 votes

Quelqu'un peut-il m'aider pour stackoverflow.com/questions/40946697/ ? Merci d'avance !

9 votes

Les déclarations doivent être enveloppées dans un script { } étape.

0 votes

...pour obtenir soit stdout soit le statut de retour...

52voto

vehovmar Points 850

La 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-26133

EDIT2 : Je ne sais pas exactement depuis quelle version, mais les étapes sh/bat peuvent maintenant retourner la sortie std, simplement :

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

2 votes

Pour votre information, les étapes bat font écho à la commande en cours d'exécution. Vous devez donc commencer les commandes bat par @ pour n'obtenir que la sortie (par exemple, "@dir").

0 votes

Au lieu de @ J'ai utilisé output = sh(script: 'command here', returnStdout: true).trim().readLines().drop(1).join(" ")

44voto

Ed Randall Points 913

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

Pipeline scénarisé

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 une méthode utile pour obtenir ce statut de sortie, donc si la valeur réelle est requise, vous devrez l'analyser à partir du message (ugh !).

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

Mise à jour : Si vous souhaitez également obtenir la sortie STDERR de la commande shell, Jenkins ne prend malheureusement pas correctement en charge ce cas d'utilisation courant. Un billet de 2017 JENKINS-44930 est coincé dans un état de ping-pong d'opinion tout en ne faisant aucun progrès vers une solution - s'il vous plaît envisager d'ajouter votre upvote à elle.

Quant à une solution maintenant il y a plusieurs approches possibles :

a) Rediriger STDERR vers STDOUT 2>&1 - mais c'est ensuite à vous de l'analyser dans la sortie principale, et vous n'obtiendrez pas la sortie si la commande a échoué - parce que vous êtes dans le gestionnaire d'exception.

b) rediriger STDERR vers un fichier temporaire (dont vous avez préparé le nom plus tôt) 2>filename (mais n'oubliez pas de nettoyer le fichier par la suite) - c'est-à-dire que 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) Aller dans l'autre sens, mettre returnStatus=true à la place, ne pas utiliser le gestionnaire d'exception et toujours capturer 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
}

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

1 votes

Y a-t-il une chance d'obtenir la sortie "ls : cannot access dir1 : No such file or directory" et pas seulement "hudson.AbortException : script returned exit code 2" ?

2 votes

Je ne vois pas comment cela pourrait fonctionner. Dans mes tests, le texte de sortie n'est jamais attribué et c'est normal. L'exception lancée par l'étape du shell empêche l'attribution de la valeur de retour.

2 votes

ReturnStatus et returnStdout ne fonctionnent malheureusement pas en même temps. Voici le ticket. S'il vous plaît, votez : questions.jenkins-ci.org/browse/JENKINS-44930 .

13voto

Bibek Mantree Points 121

Il s'agit d'un cas type, qui aura du 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]} "

    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X