¿Cómo / cuándo Execute Shell marca una compilación como falla en Jenkins?

112

Las historias de terror que encontré mientras buscaba una respuesta para esta ...

Bien, tengo un script .sh que prácticamente hace todo lo que se supone que debe hacer Jenkins:

  • comprueba las fuentes de SVN
  • construye el proyecto
  • despliega el proyecto
  • limpia después de sí mismo

Entonces, en Jenkins solo tengo que 'construir' el proyecto ejecutando el script en un comando Ejecutar Shell. El script se ejecuta (las fuentes se descargan, el proyecto se compila / implementa) pero luego marca la compilación como un error: El paso de compilación 'Ejecutar shell' marcó la compilación como falla ¡Incluso si el script se ejecutó correctamente! Intenté cerrar el guión con:

  • salida 0 (todavía lo marca como falla)
  • salida 1 (lo marca como falla, como se esperaba)
  • ningún comando de salida en absoluto (lo marca como falla)

¿Cuándo, cómo y por qué Execute Shell marca mi compilación como una falla?

ensayador
fuente

Respuestas:

131

Lo primero es lo primero, pase el mouse sobre el área gris a continuación. No es parte de la respuesta, pero es absolutamente necesario decirlo:

Si tiene una secuencia de comandos de shell que hace "pago, compilación, implementación" por sí sola, ¿por qué está usando Jenkins? Está renunciando a todas las características de Jenkins que lo convierten en lo que es. También puede hacer que un cron o un enlace posterior a la confirmación de SVN llame al script directamente. Que Jenkins realice la comprobación de SVN en sí es crucial. Permite que las compilaciones se activen solo cuando hay cambios (o en el temporizador o manual, si lo prefiere). Realiza un seguimiento de los cambios entre compilaciones. Muestra esos cambios, para que pueda ver qué compilación fue para qué conjunto de cambios. Envía correos electrónicos a los confirmantes cuando sus cambios causaron una compilación exitosa o fallida (nuevamente, según lo configurado como prefiera). Enviará un correo electrónico a los confirmadores cuando sus soluciones solucionen la compilación defectuosa. Y cada vez más. Jenkins archiva los artefactos también los hace disponibles, por construcción, directamente de Jenkins. Si bien no es tan crucial como la verificación de SVN, esto es una vez más una parte integral de lo que lo convierte en Jenkins. Lo mismo ocurre con la implementación. A menos que tenga un único entorno, la implementación suele ocurrir en varios entornos. Jenkins puede realizar un seguimiento de en qué entorno se implementa una compilación específica (con un conjunto específico de cambios de SVN), mediante el uso de Promociones. Estás renunciando a todo esto. Parece que te dicen "tienes que usar Jenkins", pero en realidad no quieres, y lo estás haciendo solo para quitarte de encima a tus jefes, solo para marcar "sí, he usado Jenkins"

La respuesta corta es: el código de salida del último comando del paso de compilación Ejecutar Shell de Jenkin es lo que determina el éxito / fracaso del Paso de compilación . 0- éxito, anything else- fracaso. Tenga en cuenta que esto determina el éxito / fracaso del paso de compilación , no la ejecución completa del trabajo . El éxito / fracaso de toda la ejecución del trabajo puede verse afectado aún más por varios pasos de compilación y acciones y complementos posteriores a la compilación.

Como ha mencionado Build step 'Execute shell' marked build as failure, nos centraremos en un solo paso de compilación. Si su paso de construcción Ejecutar shell solo tiene una línea que llama a su script de shell, entonces el código de salida de su script de shell determinará el éxito / fracaso del paso de construcción. Si tiene más líneas, después de la ejecución del script de shell, revíselas cuidadosamente, ya que son las que podrían estar causando fallas.

Finalmente, lea aquí Jenkins Build Script sale después de la ejecución de Google Test . No está directamente relacionado con su pregunta, pero tenga en cuenta esa parte sobre el lanzamiento de Jenkins del paso de compilación Ejecutar Shell , como un script de shell con/bin/sh -xe

Los -emedios que el script de shell salir con el fracaso, incluso si sólo 1 comando falla, incluso si lo hace la comprobación de errores para ese comando (porque las salidas de guión antes de que llegue a su comprobación de errores). Esto es contrario a la ejecución normal de los scripts de shell, que generalmente imprimen el mensaje de error del comando fallido (o lo redirigen a nulo y lo manejan por otros medios) y continúan.

Para evitar esto, agregue set +ea la parte superior de su script de shell.

Como dice que su secuencia de comandos hace todo lo que se supone que debe hacer, es probable que el comando que falla esté en algún lugar al final de la secuencia de comandos. ¿Quizás un eco final? ¿O copia de artefactos en alguna parte? Sin ver la salida completa de la consola, solo estamos adivinando.

Publique la salida de la consola de la ejecución del trabajo, y preferiblemente también el script de shell, y luego podríamos decirle exactamente qué línea está fallando.

eslavo
fuente
6
La razón por la que sigo usando Jenkins no me queda clara ... Parece que alguien en la parte superior no entendió del todo que ya tenemos este guión e insistió en que usáramos Jenkins. Me siento como si estuviera en una tira de Dilbert. Gracias por el consejo -e. Resolvió el problema
tester
45
Todavía hay buenas razones para usar Jenkins: la pista de auditoría, la visibilidad del estado de la compilación, etc. Si ya tiene un script de compilación, moverlo a Jenkins es un buen primer paso antes de refactorizarlo para aprovechar las características de Jenkins.
aehlke
3
El enlace cruzado de esta respuesta serverfault.com/a/143576/186454 set + ey set -e se puede especificar en cualquier lugar de su secuencia de comandos. Cualquier código intermedio no fallará en la compilación si el valor devuelto no es 0.
Alex Skrypnyk
2
muy bien dicho en el script de shell vs jenkins set
pushya
utilizamos jenkins para proporcionar acceso autenticado y una interfaz de usuario para el trabajo. Un cron no lo haría. Jenkins no solo tiene cripts.
ffghfgh
90

La respuesta simple y breve a su pregunta es

Agregue la siguiente línea en su paso de compilación "Ejecutar shell".

#!/bin/sh

Ahora déjeme explicarle la razón por la que necesitamos esta línea para el trabajo de compilación "Ejecutar Shell".

Por defecto, Jenkins toma /bin/sh -xey este medio -ximprimirá todos y cada uno de los -ecomandos, y la otra opción , que hace que el shell deje de ejecutar un script inmediatamente cuando cualquier comando sale con un código de salida distinto de cero (cuando cualquier comando falla).

Entonces, agregar el #!/bin/shle permitirá ejecutar sin opción.

Abhijeet Kamble
fuente
4
Voto a favor. No sabía sobre el -xe predeterminado. Cuando mi comando grep no encontraba una cadena, todo mi script falló porque grep devolvió un valor de retorno distinto de 0 :)
Somaiah Kumbera
¡Funcionó muy bien! Usándolo en uno de los pasos no cruciales, un paso de limpieza que simplemente hace algo como find . -name 'bower_components' -exec rm {} \;y, en algunos casos, estaba fallando. ¡Gracias!
Yorch
esto borró todo - 'Y la otra opción -e, que hace que el shell deje de ejecutar un script inmediatamente cuando cualquier comando sale con un código de salida distinto de cero (cuando cualquier comando falla).'
Paramvir Singh Karwal
3

En mi opinión, desactivar la -eopción de tu shell es una muy mala idea. Eventualmente, uno de los comandos en su script fallará debido a condiciones transitorias como falta de espacio en disco o errores de red. Sin -eJenkins no se dará cuenta y continuará felizmente. Si tiene Jenkins configurado para realizar la implementación, eso puede resultar en que se envíe un código incorrecto y se caiga su sitio.

Si tiene una línea en su secuencia de comandos donde se espera un error, como un grep o una búsqueda, simplemente agregue || trueal final de esa línea. Eso asegura que la línea siempre tendrá éxito.

Si necesita usar ese código de salida, puede incorporar el comando en su declaración if:

grep foo bar; if [ $? == 0 ]; then ...    -->   if grep foo bar; then ...

O puede capturar el código de retorno en su ||cláusula:

grep foo bar || ret=$?
Bryan Larsen
fuente
1
Gracias Bryan. Salvaste mi día . Además, creo que es una buena idea activar tanto -x como -e. Para que veas en tu registro de Jenkins.
Bikal Basnet
2

Simple y llanamente:

Si Jenkins ve que el paso de compilación (que también es un script) sale con un código distinto de cero, la compilación se marca con una bola roja (= fallida).

Por qué sucede exactamente eso depende de su script de compilación.

Escribí algo similar desde otro punto de vista, pero tal vez ayude leerlo de todos modos: ¿Por qué Jenkins cree que mi compilación tuvo éxito?

sti
fuente
0

Entonces, agregar el #!/bin/shle permitirá ejecutar sin opción.

También me ayudó a solucionar un problema en el que estaba ejecutando un script bash desde el maestro Jenkins en mi esclavo de Linux. Simplemente agregando por #!/bin/bashencima de mi secuencia de comandos real en el bloque "Ejecutar Shell", solucionó mi problema, ya que de lo contrario estaba ejecutando la versión proporcionada por git de Windows de bash shell que estaba dando un error.

Shailender Singh
fuente
0

En Jenkins ver. 1.635, es imposible mostrar una variable de entorno nativa como esta:

$BUILD_NUMBER or ${BUILD_NUMBER}

En este caso, debe configurarlo en otra variable.

set BUILDNO = $BUILD_NUMBER
$BUILDNO
usuario10413452
fuente