J'ai remarqué que de nombreux scripts entrypoint.sh pour docker font quelque chose comme ceci:
#!/bin/bash
set -e
... code ...
exec "$@"
Quels sont les set -e
et les exec "$@"
pour?
Réponses:
Il prend essentiellement tous les arguments de ligne de commande passés à entrypoint.sh
et les exécute comme une commande. L'intention est fondamentalement "Faites tout dans ce script .sh, puis dans le même shell exécutez la commande que l'utilisateur transmet sur la ligne de commande".
Voir:
exec "$@"
remplacera le processus en cours d'exécution par le nouveau processus généré pour les arguments passés. Important pour la signalisation Docker: stackoverflow.com/a/32261019/99717
set -e
définit une option shell pour quitter immédiatement si une commande en cours d'exécution se termine avec un code de sortie différent de zéro. Le script retournera avec le code de sortie de la commande ayant échoué. Depuis la page de manuel de bash:
set -e:
Quittez 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), se termine avec un état différent de zéro. Le shell ne se ferme pas si la commande qui échoue fait partie de la liste de commandes suivant immédiatement un mot-clé while ou until, une partie du test suivant les mots réservés if ou elif, une partie de toute commande exécutée dans un && ou || list sauf 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 avec!. Si une commande composée autre qu'un sous-shell renvoie un état différent de zéro car une commande a échoué alors que -e était ignoré, le shell ne se ferme pas. Un trap sur ERR, s'il est défini, est exécuté avant la sortie du 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 la commande composée ou le corps de la fonction ne sera affectée par le paramètre -e, même si -e est défini et une commande renvoie un état d'échec. Si une commande composée ou une fonction shell définit -e lors de l'exécution dans un contexte où -e est ignoré, ce paramètre n'aura aucun effet tant que la commande composée ou la commande contenant l'appel de fonction ne sera pas terminée.
exec "$@"
est généralement utilisé pour faire du point d'entrée un passage qui exécute ensuite la commande docker. Il remplacera le shell en cours d'exécution par la commande qui "$@"
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
, cela se traduira par une exécution entrypoint.sh server start
dans le conteneur. À la ligne exec entrypoint.sh
, le shell fonctionnant en tant que pid 1 se remplacera par la commande server start
.
Ceci est essentiel pour la gestion du signal. Sans utiliser exec
, server start
dans l'exemple ci-dessus s'exécuterait comme un autre pid, et après sa sortie, vous reviendriez à votre script shell. Avec un shell en pid 1, un SIGTERM sera ignoré par défaut. Cela signifie que le signal d'arrêt progressif qui docker stop
envoie à votre conteneur ne sera jamais reçu par le server
processus. Après 10 secondes (par défaut), docker stop
abandonnerait l'arrêt progressif et enverrait un SIGKILL qui forcerait votre application à se fermer, mais avec une perte de données potentielle ou des connexions réseau fermées, que les développeurs d'applications auraient pu coder s'ils recevaient 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
et set --
, vous pouvez modifier la valeur de "$@"
. Par exemple, voici une courte partie d'un script qui supprime le /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 "$@"
test
spécification POSIX , qui marque l' -a
obsolescence. [ "$#" -gt 1 ] && [ "$1" = /bin/sh ]
est le bon remplacement (il n'y a pas besoin de x"$1"
piratage lorsque vous utilisez uniquement la syntaxe non obsolète).
shift 2; set -- $1
n'est pas du tout la même chose que la façon dont eval
analysera la chaîne. Considérez /bin/sh -c 'printf "%s\n" "hello world" "goodbye world"'
, si vous voulez un cas de test concret, et voyez que Bash n'analyse pas les guillemets lors de la conversion d'une chaîne en arguments .
eval
, je crois que je veux toujours que cela reflète le comportement de l' /bin/sh -c
aurait sur la chaîne, mais s'il vous plaît laissez-moi savoir si je manque quelque chose.
set -e
- quitter le script si une commande échoue (valeur non nulle)
exec "$@"
- redirigera les variables d'entrée, voir plus ici
exec
a certainement un mode d'utilisation où il effectue des redirections, mais ce n'est pas ce mode.
set -e
est considéré comme beaucoup plus sujet aux erreurs que la gestion des erreurs manuscrites. (Si vous êtes pressé, sautez l'analogie en haut pour les exercices ci-dessous).