2017-10-19 18 views
1

Nous avons récemment déménagé à Gitlab et avons commencé à utiliser des pipelines. Nous avons mis en place un serveur de build (une instance Ubuntu 16.04) et installé un coureur qui utilise un exécuteur Shell mais je ne suis pas sûr de la façon dont il exécute réellement les scripts définis dans le fichier .gitlab-ci.yml. Considérons l'extrait de code suivant:Comment l'exécuteur Shell exécute-t-il les scripts?

script: 
    - sh authenticate.sh $DEPLOY_KEY 
    - cd MAIN && sh deploy.sh && cd .. 
    - sh deploy_service.sh MATCHMAKING 
    - sh deauthenticate.sh 

j'avais l'impression que ce sera juste conduit ces commandes à Bash, et donc je me attendais le comportement de Bash par défaut. Qu'est-ce qui se passe, cependant, est que le deploy.sh échoue en raison d'une erreur ssh; Bash continue alors à exécuter deploy_service.sh (ce qui est un comportement attendu) mais cela échoue avec une erreur can't open deploy_service.sh et le travail se termine sans que Bash n'exécute la dernière instruction. D'après ce que je comprends, Bash n'abandonnera en cas d'erreur que si vous faites d'abord un set -e et donc je m'attendais à ce que toutes les instructions soient exécutées. J'ai essayé d'ajouter le set -e comme première instruction mais cela ne fait aucune différence - il ne se termine pas sur la première erreur ssh.

J'ai ajouté la sortie exacte de gitlab ce ci-dessous:

Sans set -e

$ cd MAIN && sh deploy.sh && cd .. 
deploy.sh: 72: deploy.sh: Bad substitution 
Building JS bundles locally... 

> better-npm-run build 

running better-npm-run in x 
Executing script: build 

to be executed: node ./bin/build 
-> building js bundle... 
-> minifying js bundle... 
Uploading JS bundles to server temp folder... 
COMMENCING RESTART. 5,4,3,2,1... 
ssh: Could not resolve hostname $: Name or service not known 
$ sh deploy_service.sh MATCHMAKING 
sh: 0: Can't open deploy_service.sh 
ERROR: Job failed: exit status 1 

Avec set -e

$ set -e 
$ cd MAIN && sh deploy.sh && cd .. 
deploy.sh: 72: deploy.sh: Bad substitution 
Building JS bundles locally... 

> better-npm-run build 

running better-npm-run in x 
Executing script: build 

to be executed: node ./bin/build 
-> building js bundle... 
-> minifying js bundle... 
Uploading JS bundles to server temp folder... 
COMMENCING RESTART. 5,4,3,2,1... 
ssh: Could not resolve hostname $: Name or service not known 
$ sh deploy_service.sh MATCHMAKING 
sh: 0: Can't open deploy_service.sh 
ERROR: Job failed: exit status 1 

Pourquoi est-il, sans set -e, se terminant en cas d'erreur (également, pourquoi se termine-t-il uniquement sur la deuxième erreur et non sur l'erreur ssh)? Toute idée serait grandement appréciée.

+2

« sh deploy.sh » Vous invoquer 'sh' ici, pas 'bash'. Ils peuvent ne pas être la même chose sur votre système. Si vous voulez bash, appelez bash. – Kenster

+0

@Kenster 'bash' est utilisé pour invoquer' sh' sur ce script et l'erreur est renvoyée 'bash' avec le code de sortie approprié (127 pour la première erreur et 255 pour la deuxième erreur). Le problème est que 'bash' est/ne détecte pas l'erreur comme prévu. – Amposter

+0

De la docs: # Cette commande est utilisée si la construction doit être exécutée dans le contexte d'un autre utilisateur (l'interpréteur de shell) 'cat generated-bash-script | su --shell/bin/bash --login user' – Amposter

Répondre

0

Le bloc de script Gitlab est un ensemble de scripts shell. https://docs.gitlab.com/ee/ci/yaml/#script Echec dans chaque élément de tableau échouera un tableau entier. Pour contourner mettre votre bloc de script dans un fichier d'script.sh

comme

script: 
    - ./script.sh 
0

Je ne pense pas que votre sh deploy.sh génère un code de sortie non nul.

Vous utilisez set -e pour indiquer au processus en cours de quitter si une commande se termine avec un code retour différent de zéro, mais vous créez un sous-processus pour exécuter le script shell.

Voici un simple exemple de script que j'ai appelé deploy.sh:

#!/bin/bash 
echo "First." 
echox "Error" 
echo "Second" 

Si je lance le script, vous pouvez voir comment l'erreur est pas traitée:

$ sh deploy.sh 
First. 
deploy.sh: line 5: echox: command not found 
Second 

Si je lance set -e D'abord, vous verrez que cela n'a aucun effet.

$ set -e 
$ sh deploy.sh 
First. 
deploy.sh: line 5: echox: command not found 
Second 

Maintenant, j'ajouter -e au /bin/bash tralala:

#!/bin/bash -e 
echo "First." 
echox "Error" 
echo "Second" 

Quand je lance le script avec sh le -eencore prend aucun effet.

$ sh ./deploy.sh 
First. 
./deploy.sh: line 3: echox: command not found 
Second 

Lorsque ce script est exécuté directement en utilisant bash, le -e prend effet.

$ ./deploy.sh 
First. 
./deploy.sh: line 3: echox: command not found 

Pour résoudre votre problème, je crois que vous devez:

  • Ajouter -e à la ligne shebang du script (#!/bin/bash -e)
  • appeler le script direct de bash en utilisant ./deploy.sh et non exécutez le script par sh.

Gardez à l'esprit que si deploy.shne échouent alors le cd .. sera pas course (&& moyens exécutez la commande suivante si la précédente a réussi), ce qui voudrait dire que vous étiez dans le mauvais répertoire pour exécuter le deploy_service.sh. Vous seriez mieux avec cd MAIN; sh deploy.sh; cd .., mais je suggère de remplacer votre appel à deploy.sh avec alternative plus simple:

script: 
    - sh authenticate.sh $DEPLOY_KEY 
    - (cd MAIN && sh deploy.sh) 
    - sh deploy_service.sh MATCHMAKING 
    - sh deauthenticate.sh 

Ce n'est pas très différentes, mais entraînera la cd MAIN && sh deploy.sh à exécuter dans un sous-processus (c'est ce que le parenthèses), ce qui signifie que le répertoire courant du script global n'est pas affecté. Pensez-y comme "générer un sous-processus, et dans le sous-processus changer de répertoire et exécuter ce script", et lorsque le sous-processus se termine, vous finissez par où vous avez commencé.

Comme d'autres utilisateurs ont commenté, vous êtes en train de l'exécution de vos scripts dans sh, bash pas, si toute cela pourrait être mieux:

script: 
    - ./authenticate.sh $DEPLOY_KEY 
    - (cd MAIN && ./deploy.sh) 
    - ./deploy_service.sh MATCHMAKING 
    - ./deauthenticate.sh 
+0

'deploy.sh' renvoie un code de sortie différent de zéro (j'utilise' set -e' dans le script et j'ai vérifié la variable '$?' plusieurs fois). Je suis au courant de la mise en garde «&&» et pourquoi la déclaration suivante échoue, mais c'est d'ailleurs le point. Le point est que les deux lignes ('cd MAIN && sh deploy.sh && cd .. 'et' sh deploy_service.sh MATCHMAKING') renvoient des codes de sortie non nuls, mais l'exécuteur ne fait qu'errer sur le deuxième échec de la déclaration. – Amposter