Voir BashFAQ # 105 re: pourquoi set -eest 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).
Charles Duffy
Réponses:
70
Il prend essentiellement tous les arguments de ligne de commande passés à entrypoint.shet 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".
Notez également que 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
Hawkeye Parker
34
set -edé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 startdans 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 startdans 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 stopenvoie à votre conteneur ne sera jamais reçu par le serverprocessus. Après 10 secondes (par défaut), docker stopabandonnerait 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 shiftet 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:
Voir la testspécification POSIX , qui marque l' -aobsolescence. [ "$#" -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).
@CharlesDuffy merci pour le conseil sur l'option obsolète, je suis sûr que je vais refaire cette erreur, les vieilles habitudes meurent dur. Avec le eval, je crois que je veux toujours que cela reflète le comportement de l' /bin/sh -caurait sur la chaîne, mais s'il vous plaît laissez-moi savoir si je manque quelque chose.
BMitch
30
set -e - quitter le script si une commande échoue (valeur non nulle)
exec "$@"- redirigera les variables d'entrée, voir plus ici
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).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:
la source
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/99717set -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: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écutionentrypoint.sh server start
dans le conteneur. À la ligne execentrypoint.sh
, le shell fonctionnant en tant que pid 1 se remplacera par la commandeserver 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 quidocker stop
envoie à votre conteneur ne sera jamais reçu par leserver
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
etset --
, 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 pourCMD
:# 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 "$@"
la source
test
spécification POSIX , qui marque l'-a
obsolescence.[ "$#" -gt 1 ] && [ "$1" = /bin/sh ]
est le bon remplacement (il n'y a pas besoin dex"$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 donteval
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 icila source
exec
a certainement un mode d'utilisation où il effectue des redirections, mais ce n'est pas ce mode.