J'ai remarqué que de nombreux scripts d'entrypoint.sh pour docker font quelque chose comme ça :
#!/bin/bash
set -e
... code ...
exec "$@"
Quels sont les set -e
et le exec "$@"
pour ?
J'ai remarqué que de nombreux scripts d'entrypoint.sh pour docker font quelque chose comme ça :
#!/bin/bash
set -e
... code ...
exec "$@"
Quels sont les set -e
et le exec "$@"
pour ?
Notez également que exec "$@"
remplacera le processus en cours d'exécution par le nouveau processus créé pour les arguments passés. Important pour la signalisation Docker : stackoverflow.com/a/32261019/99717
set -e
définit une option de l'interpréteur de commandes pour quitter immédiatement si une commande en cours d'exécution sort avec un code de sortie non nul. Le script reviendra avec le code de sortie de la commande défaillante. Extrait de la page de manuel de bash :
set -e :
Sortir immédiatement si un pipeline (qui peut consister en une seule commande simple), une liste, ou une commande composée (voir SHELL GRAMMAR ci-dessus), sort avec un état non nul. Le shell ne sort pas si la commande qui échoue fait partie de la liste de commandes qui suit immédiatement immédiatement après un mot-clé while ou until, une partie du test après les mots réservés if ou elif, une partie de toute commande exécutée dans une liste && ou ||. à l'exception de la commande suivant le && ou || final, toute commande dans un pipeline sauf la dernière, ou si la valeur de retour de la commande est inversée par !. Si une commande composée autre qu'un sous-shell renvoie un état non nul parce qu'une commande a échoué pendant que -e était était ignoré, le shell ne se termine pas. Un piège sur ERR, s'il est défini, est exécuté avant que le shell ne se termine. Cette option s'applique à l'environnement du shell et à chaque environnement de sous-shell séparément (voir l'ENVIRONNEMENT D'EXÉCUTION DE COMMANDES ci-dessus), et peut provoquer la sortie des sous-shells avant l'exécution de avant d'avoir exécuté toutes les commandes du sous-shell.
Si une commande composée ou une fonction shell s'exécute dans un contexte où -e est ignoré, aucune des commandes exécutées dans le corps de la commande composée ou de la fonction ne sera affectée par le paramètre -e, même si le paramètre -e est défini et qu'une commande renvoie un état d'échec. Si une commande composée ou une fonction shell définit -e alors qu'elle s'exécute dans un contexte où -e est ignoré, ce paramètre n'aura aucun effet jusqu'à ce que la commande composée ou la commande contenant l'appel de fonction se termine.
exec "$@"
est généralement utilisé pour faire du point d'entrée un passage qui exécute ensuite la commande Docker. Elle remplacera le shell en cours d'exécution par la commande que "$@"
pointe vers. Par défaut, cette variable pointe vers les arguments de la ligne de commande.
Si vous avez une image avec un point d'entrée pointant vers entrypoint.sh, et que vous exécutez votre conteneur en tant que docker run my_image server start
qui se traduira par une course à pied entrypoint.sh server start
dans le conteneur. A la ligne d'exécution entrypoint.sh
le shell s'exécutant sous pid 1 se remplacera par la commande server start
.
Ceci est essentiel pour le traitement des signaux. Sans utiliser exec
le server start
dans l'exemple ci-dessus s'exécuterait comme un autre pid, et après qu'il soit sorti, vous retourneriez à votre shell script. Avec un shell en pid 1, un SIGTERM sera ignoré par défaut. Cela signifie que le signal d'arrêt gracieux que docker stop
envoie à votre conteneur, ne serait jamais reçu par le server
processus. Après 10 secondes (par défaut), docker stop
abandonne l'arrêt gracieux et envoie un SIGKILL qui force votre application à se terminer, mais avec une perte de données potentielle ou des connexions réseau fermées, que les développeurs d'applications auraient pu contourner s'ils avaient reçu le signal. Cela signifie également que votre conteneur prendra toujours les 10 secondes pour s'arrêter.
Notez qu'avec des commandes shell comme shift
y set --
vous pouvez modifier la valeur de "$@"
. Par exemple, voici une courte partie d'un script qui supprime l'élément /bin/sh -c "..."
de la commande qui peut apparaître si vous utilisez la syntaxe shell de docker pour CMD
:
# convert `/bin/sh -c "server start"` to `server start`
if [ $# -gt 1 ] && [ x"$1" = x"/bin/sh" ] && [ x"$2" = x"-c" ]; then
shift 2
eval "set -- $1"
fi
....
exec "$@"
Voir la norme POSIX test
spec qui marque -a
obsolète. [ "$#" -gt 1 ] && [ "$1" = /bin/sh ]
est le remplacement correct (il n'y a pas besoin de l'option x"$1"
en utilisant uniquement la syntaxe non obsolète).
Aussi, shift 2; set -- $1
n'est pas du tout la même chose que la façon dont eval
analysera la chaîne de caractères. Considérons /bin/sh -c 'printf "%s\n" "hello world" "goodbye world"'
si vous voulez un cas de test concret, et voir Bash n'analyse pas les guillemets lors de la conversion d'une chaîne en arguments .
@CharlesDuffy merci pour l'astuce sur l'option obsolète, je suis sûr que je vais refaire cette erreur, les vieilles habitudes ont la vie dure. Avec le eval
je crois que je veux toujours que cela reflète le comportement de /bin/sh -c
aurait sur la chaîne, mais faites-moi savoir si je manque quelque chose.
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.
5 votes
Voir BashFAQ #105 pourquoi
set -e
est considérée comme beaucoup plus sujette aux erreurs que la gestion des erreurs écrite à la main. (Si vous êtes pressé, sautez l'analogie en haut pour les exercices ci-dessous).