¿Cómo puedo ejecutar el resultado de un comando de shell usando una variable de Jenkinsfile (groovy)?

Resuelto sorin asked hace 54 años • 10 respuestas

Tengo algo como esto en un archivo Jenkins (Groovy) y quiero registrar la salida estándar y el código de salida en una variable para poder usar la información más adelante.

sh "ls -l"

¿Cómo puedo hacer esto, especialmente porque parece que realmente no se puede ejecutar ningún tipo de código maravilloso dentro del archivo Jenkinsfile?

sorin avatar Jan 01 '70 08:01 sorin
Aceptado

La última versión del shpaso de canalización le permite hacer lo siguiente;

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

Otra característica es la returnStatusopció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}"

Estas opciones se agregaron en función de este problema.

Consulte la documentación oficial del shcomando.

Para canalizaciones declarativas (ver comentarios), debe ajustar el código al scriptpaso:

script {
   GIT_COMMIT_EMAIL = sh (
        script: 'git --no-pager show -s --format=\'%ae\'',
        returnStdout: true
    ).trim()
    echo "Git committer email: ${GIT_COMMIT_EMAIL}"
}
G. Roggemans avatar Aug 05 '2016 07:08 G. Roggemans

La versión actual de Pipeline admite de forma nativa returnStdouty returnStatus, lo que permite obtener resultados o estados de los pasos sh/ bat.

Un ejemplo:

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

Una documentación oficial .

luka5z avatar Oct 12 '2016 20:10 luka5z

la respuesta rápida es esta:

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

Creo que existe una solicitud de función para poder obtener el resultado del paso sh, pero hasta donde yo sé, actualmente no hay otra opción.

EDITAR: JENKINS-26133

EDIT2: No estoy seguro de qué versión, pero los pasos de sh/bat ahora pueden devolver la salida estándar, simplemente:

def output = sh returnStdout: true, script: 'ls -l'
vehovmar avatar Apr 11 '2016 13:04 vehovmar

Si desea obtener la salida estándar Y saber si el comando se realizó correctamente o no, simplemente úselo returnStdouty envuélvalo en un controlador de excepciones:

canalización con guión

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

producción :

[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

Desafortunadamente, a hudson.AbortException le falta algún método útil para obtener ese estado de salida, por lo que si se requiere el valor real, deberá analizarlo y eliminarlo del mensaje (¡uf!).

Al contrario del Javadoc https://javadoc.jenkins-ci.org/hudson/AbortException.html , la compilación no falla cuando se detecta esta excepción. ¡Falla cuando no se atrapa!

Actualización: si también desea la salida STDERR del comando de shell, lamentablemente Jenkins no admite adecuadamente ese caso de uso común. Un ticket de 2017, JENKINS-44930 , está atascado en un estado de ping-pong obstinado sin avanzar hacia una solución; considere agregarle su voto a favor.

En cuanto a una solución ahora , podría haber un par de enfoques posibles:

a) Redirigir STDERR a STDOUT 2>&1 , pero depende de usted analizarlo de la salida principal, y no obtendrá la salida si el comando falla, porque está en el controlador de excepciones.

b) redirigir STDERR a un archivo temporal (cuyo nombre preparó anteriormente) 2>filename(pero recuerde limpiar el archivo después), es decir. El código principal se convierte en:

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) Vaya al otro lado, configúrelo returnStatus=true, prescinda del controlador de excepciones y capture siempre la salida en un archivo, es decir:

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
}

Advertencia: el código anterior es específico de Unix/Linux: Windows requiere comandos de shell completamente diferentes.

Ed Randall avatar Nov 12 '2018 00:11 Ed Randall