Set-e 和 exec“ $@”对 docker 入口点脚本有什么作用?

我注意到很多用于 docker 的 entrypoint.sh 脚本都是这样做的:

#!/bin/bash
set -e


... code ...


exec "$@"

set -eexec "$@"是用来干什么的?

85780 次浏览

它基本上接受传递给 entrypoint.sh的任何命令行参数,并将它们作为命令执行。其目的基本上是“在这里做所有的事情。Sh 脚本,然后在同一个 shell 中运行用户在命令行上传入的命令”。

参见:

set -e-退出脚本,如果任何命令失败(非零值)

将重定向输入变量,请参阅更多的 给你

set -e设置一个 shell 选项,如果正在运行的任何命令使用非零退出代码退出,该选项将立即退出。该脚本将返回失败命令的退出代码。来自 bash 手册页:

集 e:

如果管道(可能由单个简单命令组成)、列表或复合命令(参见 SHELL) ,则立即退出 (上面的语法) ,以非零状态退出。 shell 不退出 如果失败的命令立即成为命令列表的一部分 跟随一段时间或直到关键字后面,测试的一部分跟随 if 或 elif 保留字,在 & & 或 | | 中执行的任何命令的一部分 列表,除了最终 & & 或 | | 后面的命令之外 命令在管道中但是最后一个,或者如果命令的返回值 如果不是子 shell 的复合命令 返回一个非零状态,因为当 -e 正在执行时命令失败 如果忽略,则不退出 shell。如果设置了 ERR 陷阱,则执行 ERR 陷阱 这个选项适用于 shell 环境 以及每个子 shell 环境(请参见 COMMAND ExecutION) (上面的 ENVIRONMENT) ,并且可能导致子 shell 在执行之前退出 子 shell 中的所有命令。

如果复合命令或 shell 函数在以下上下文中执行,则为 - e 被忽略,复合命令或函数体中执行的任何命令都不会受到-e 设置的影响,即使 - e 已设置,命令返回失败状态。如果复合命令或 shell 函数在以下上下文中执行时设置-e - e,则该设置在复合命令或包含函数调用的命令之前不会有任何效果 完成。


exec "$@"通常用于使入口点成为一个通道,然后运行 docker 命令。它将用 "$@"指向的命令替换当前正在运行的 shell。默认情况下,该变量指向命令行参数。

如果您有一个具有指向 entrypoint.sh 的入口点的映像,并且以 docker run my_image server start的形式运行容器,那么这将转化为在容器中运行 entrypoint.sh server start。在 exec 行 entrypoint.sh中,作为 pid 1运行的 shell 将使用命令 server start替换自身。

这对信号处理至关重要。如果不使用 exec,上面示例中的 server start将作为另一个 pid 运行,退出后将返回到 shell 脚本。在 pid 1中使用 shell 时,默认情况下将忽略 SIGTERM。这意味着优雅的停止信号,docker stop发送到您的容器,将永远不会收到的 server进程。10秒后(默认情况下) ,docker stop会放弃优雅的关机,发送一个 SIGKILL 信号迫使你的应用退出,但由于潜在的数据丢失或网络连接关闭,应用程序开发人员可以编码,如果他们收到信号。这也意味着您的容器总是需要10秒钟停止。

注意,使用像 shiftset --这样的 shell 命令,您可以更改 "$@"的值。例如,下面是一个脚本的一小部分,它从命令中删除了 /bin/sh -c "...",如果你对 CMD使用 docker 的 shell 语法,就会出现这个命令:

# 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 "$@"