Какая цель заключается в использовании exec в сценариях входа в докер?
Например, в официальном изображении redis:
https://github.com/docker-library/redis/blob/master/2.8/docker-entrypoint.sh
#!/bin/bash
set -e
if [ "$1" = 'redis-server' ]; then
chown -R redis .
exec gosu redis "[email protected]"
fi
exec "[email protected]"
Почему бы просто не запускать команды как обычно без exec, предшествующих им?
Ответы
Ответ 1
Как пишет @Peter Lyons, использование exec заменит родительский процесс, а не будет работать два процесса.
Это важно в Docker для правильного проксирования сигналов. Например, если Redis был запущен без exec, он не получит SIGTERM
on docker stop
и не получит возможность отключиться. В некоторых случаях это может привести к потере данных или к зомби-процессам.
Если вы запускаете дочерние процессы (т.е. не используете exec), родительский процесс становится ответственным за обработку и пересылку сигналов по мере необходимости. Это одна из причин, по которой лучше использовать супервизор или подобное при запуске нескольких процессов в контейнере, так как он будет передавать сигналы соответствующим образом.
Ответ 2
Без exec процесс родительской оболочки выживает и ждет, пока ребенок выйдет. С exec, дочерний процесс полностью заменяет родительский процесс, поэтому, когда родительскому процессу ничего не нужно делать после разворачивания дочернего элемента, я бы рассмотрел exec
немного более точный/правильный/эффективный. В великой схеме вещей я считаю, что, вероятно, безопасно классифицировать ее как небольшую оптимизацию.
без exec
- начинается родительская оболочка
- родительский shell forks child
- выполняется дочерний
- дочерние выходы
- родительская оболочка выходит
с exec
- начинается родительская оболочка
- родительская оболочка виляет дочерний элемент, заменяет собой дочерний
- дочерняя программа запускает процесс оболочки
- дочерние выходы
Ответ 3
Подумайте об этом как о оптимизации, например, о рекурсии хвоста.
Если запуск другой программы - это заключительный акт оболочки script, то не требуется слишком много времени, чтобы оболочка запускала программу в новом процессе и ждала ее. Используя exec
, процесс оболочки заменяет собой программу.
В любом случае выходное значение оболочки script будет идентичным 1. Какая бы программа изначально называлась оболочкой script, будет видно значение выхода, равное значению выхода программы exec (или 127, если программа не может быть найдена).
1 по модулю угловых случаев, таких как программа, выполняющая что-то другое в зависимости от имени своего родителя.