Como / quando o Execute Shell marca um build como falha no Jenkins?

112

As histórias de terror que encontrei enquanto procurava uma resposta para esta ...

OK, eu tenho um script .sh que faz praticamente tudo que Jenkins deveria fazer:

  • verifica as fontes do SVN
  • construir o projeto
  • implanta o projeto
  • limpa depois de si mesmo

Portanto, no Jenkins, só preciso 'construir' o projeto executando o script em um comando Execute Shell. O script é executado (as fontes são baixadas, o projeto é compilado / implantado), mas então ele marca a compilação como uma falha: Etapa de compilação 'Executar shell' marcada como falha Mesmo se o script foi executado com sucesso! Tentei fechar o script com:

  • saída 0 (ainda marca como falha)
  • saída 1 (marca como falha, conforme o esperado)
  • nenhum comando de saída (marca como falha)

Quando, como e por que Executar Shell marca minha construção como uma falha?

testador
fonte

Respostas:

131

Em primeiro lugar, passe o mouse sobre a área cinza abaixo. Não faz parte da resposta, mas tem que ser dito:

Se você tem um script de shell que faz "checkout, build, deploy" sozinho, por que está usando o Jenkins? Você está renunciando a todos os recursos do Jenkins que o tornam o que é. Você também pode ter um cron ou um gancho post-commit SVN para chamar o script diretamente. Jenkins realizar a própria verificação do SVN é crucial. Permite que as compilações sejam acionadas apenas quando houver alterações (ou no cronômetro, ou manual, se preferir). Ele mantém o controle das mudanças entre as compilações. Ele mostra essas mudanças, para que você possa ver qual construção foi para qual conjunto de mudanças. Ele envia um e-mail aos committers quando suas mudanças causam sucesso ou falha na construção (novamente, conforme configurado como você preferir). Ele enviará um e-mail aos committers quando suas correções consertarem a compilação com falha. E cada vez mais. O arquivamento dos artefatos pelo Jenkins também os torna disponíveis, por compilação, diretamente do Jenkins. Embora não seja tão crucial quanto o check-out do SVN, mais uma vez é parte integrante do que o torna Jenkins. Mesmo com a implantação. A menos que você tenha um único ambiente, a implantação geralmente acontece em vários ambientes. O Jenkins pode acompanhar em qual ambiente uma construção específica (com um conjunto específico de alterações de SVN) é implantada, por meio do uso de Promoções. Você está renunciando a tudo isso. Parece que disseram "você tem que usar o Jenkins", mas você realmente não quer, e está fazendo isso apenas para tirar seus chefes do seu pé, apenas para colocar uma marca de seleção "sim, usei o Jenkins"

A resposta curta é: o código de saída do último comando da etapa de compilação Execute Shell do Jenkin é o que determina o sucesso / falha da etapa de compilação . 0- sucesso, anything else- fracasso. Observe que isso está determinando o sucesso / falha da etapa de construção , não a execução de toda a tarefa . O sucesso / falha de toda a execução do job pode ser ainda mais afetado por várias etapas de construção e ações e plug-ins pós-construção.

Você mencionou Build step 'Execute shell' marked build as failure, então vamos nos concentrar apenas em uma única etapa de construção. Se sua etapa de compilação Executar shell tiver apenas uma linha que chama seu script de shell, o código de saída de seu script de shell determinará o sucesso / falha da etapa de compilação. Se você tiver mais linhas, após a execução do script de shell, revise-as cuidadosamente, pois são as que podem estar causando a falha.

Por fim, leia aqui o Jenkins Build Script sai após a execução do Google Test . Não está diretamente relacionado à sua pergunta, mas observe aquela parte sobre o Jenkins iniciar a etapa de compilação Execute Shell , como um script de shell com/bin/sh -xe

Os -emeios que o shell script vai sair com o fracasso, mesmo que apenas 1 comando falhar, mesmo se você fizer a verificação de erros para esse comando (porque as saídas de script antes que ele chegue à sua verificação de erros). Isso é contrário à execução normal de scripts de shell, que geralmente imprimem a mensagem de erro para o comando com falha (ou redirecionam para nulo e tratam por outros meios) e continuam.

Para contornar isso, adicione set +eao início de seu script de shell.

Como você diz que seu script faz tudo o que deve fazer, é provável que o comando com falha esteja em algum lugar no final do script. Talvez um eco final? Ou cópia de artefatos em algum lugar? Sem ver a saída completa do console, estamos apenas adivinhando.

Poste a saída do console da execução do job e, de preferência, o próprio script de shell também, e então poderemos dizer exatamente qual linha está falhando.

eslavo
fonte
6
O motivo pelo qual ainda uso o Jenkins não está claro para mim ... Parece que alguém no topo não entendeu muito bem que já temos esse script e insistiu que usássemos o Jenkins. Eu me sinto como se estivesse em uma tira de Dilbert. Obrigado pela dica -e. Isso resolveu o problema
testador de
45
Ainda há boas razões para usar o Jenkins: a trilha de auditoria, visibilidade do status da construção, etc. Se você já tem um script de construção, movê-lo para o Jenkins é um bom primeiro passo antes de refatorá-lo para aproveitar as vantagens dos recursos do Jenkins.
aehlke
3
A reticulação desta resposta serverfault.com/a/143576/186454 set + e e set -e podem ser especificados em qualquer lugar em seu script. Qualquer código intermediário não falhará na construção se o valor retornado não for 0.
Alex Skrypnyk
2
muito bem dito sobre o script de shell vs conjunto jenkins
pushya
usamos jenkins para fornecer acesso autenticado e uma IU para o trabalho. Um cron não o cortaria. Jenkins não se limita a executar aleijados.
ffghfgh
90

Uma resposta simples e curta para sua pergunta é

Adicione a seguinte linha na etapa de compilação "Executar shell".

#!/bin/sh

Agora, deixe-me explicar o motivo pelo qual exigimos essa linha para o trabalho de construção "Execute Shell".

Por padrão, o Jenkins leva /bin/sh -xee isso significa -xque imprimirá todos os comandos. E a outra opção -e, que faz com que o shell pare de executar um script imediatamente quando qualquer comando sai com código de saída diferente de zero (quando qualquer comando falha).

Portanto, adicionar o #!/bin/shpermitirá que você execute sem opção.

Abhijeet Kamble
fonte
4
Votado. Não sabia sobre o padrão -xe. Quando meu comando grep não estava encontrando uma string, todo o meu script falhou porque o grep retornou um valor de retorno diferente de 0 :)
Somaiah Kumbera
Funcionou muito bem! Usá-lo em minhas etapas não cruciais, uma etapa de limpeza que apenas faz algo parecido find . -name 'bower_components' -exec rm {} \;e, em alguns casos, estava falhando. Obrigado!
yorch
isto limpou tudo - 'E a outra opção -e, que faz com que o shell pare de executar um script imediatamente quando qualquer comando sai com código de saída diferente de zero (quando qualquer comando falha).'
Paramvir Singh Karwal
3

Na minha opinião, desligar a -eopção de shell é uma péssima ideia. Eventualmente, um dos comandos em seu script falhará devido a condições transitórias, como falta de espaço em disco ou erros de rede. Sem -eJenkins não notará e continuará feliz. Se você configurou o Jenkins para fazer a implantação, isso pode resultar no envio de código incorreto e na desativação do seu site.

Se você tiver uma linha em seu script onde a falha é esperada, como um grep ou um find, basta adicionar || trueno final dessa linha. Isso garante que a linha sempre retornará sucesso.

Se precisar usar esse código de saída, você pode inserir o comando em sua instrução if:

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

Ou você pode capturar o código de retorno em sua ||cláusula:

grep foo bar || ret=$?
Bryan Larsen
fonte
1
Obrigado Bryan. Você salvou meu dia. Além disso, acho que é uma boa ideia ativar -x e -e. Para que você veja em seu log Jenkins.
Bikal Basnet
2

Claro e simples:

Se Jenkins vir a etapa de construção (que também é um script) sai com código diferente de zero, a construção é marcada com uma bola vermelha (= falha).

Por que exatamente isso acontece depende do seu script de construção.

Escrevi algo semelhante de outro ponto de vista, mas talvez ajude a ler de qualquer maneira: Por que o Jenkins acha que minha construção foi bem-sucedida?

sti
fonte
0

Portanto, adicionar o #!/bin/shpermitirá que você execute sem opção.

Também me ajudou a consertar um problema em que eu estava executando o script bash do mestre Jenkins no meu escravo Linux. Apenas adicionando #!/bin/bashacima do meu script real no bloco "Execute Shell" ele corrigiu meu problema, caso contrário, ele estava executando a versão do shell bash fornecida pelo git do Windows que apresentava um erro.

Shailender Singh
fonte
0

Em Jenkins ver. 1.635, é impossível mostrar uma variável de ambiente nativo como esta:

$BUILD_NUMBER or ${BUILD_NUMBER}

Neste caso, você deve configurá-lo em outra variável.

set BUILDNO = $BUILD_NUMBER
$BUILDNO
user10413452
fonte