set -e和exec"$ @"为docker入口点脚本做了什么?

Nat*_*han 69 shell docker

我注意到docker的许多entrypoint.sh脚本都是这样的:

#!/bin/bash
set -e

... code ...

exec "$@"
Run Code Online (Sandbox Code Playgroud)

什么是set -eexec "$@"为什么?

Mat*_*hew 55

它基本上采用所有额外的命令行参数并将它们作为命令执行.目的基本上是"在此.sh脚本中执行所有操作,然后在同一个shell中运行用户在命令行上传入的命令".

看到:

  • 另请注意,“exec“$@””将用为传递的参数生成的新进程替换当前正在运行的进程。对于 Docker 信号传输很重要:/sf/answers/2258271361/ (2认同)

agi*_*lob 28

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

exec "$@"- 将重定向输入变量,请在此处查看更多信息


BMi*_*tch 25

set -e如果正在运行的任何命令以非零退出代码退出,则设置shell选项以立即退出.该脚本将返回失败命令的退出代码.从bash手册页:

set -e:

如果管道(可能包含单个简单命令),列表或复合命令(请参阅上面的SHELL GRAMMAR),则立即退出,并以非零状态退出.如果失败的命令是紧跟在while或until关键字之后的命令列表的一部分,在if或elif保留字之后的测试的一部分,在&&或||中执行的任何命令的一部分,则shell不会退出 list除了最后的&&或||之后的命令,管道中的任何命令但是最后一个命令,或者命令的返回值是否被反转!如果子shell以外的复合命令返回非零状态,因为在忽略-e时命令失败,则shell不会退出.ERR上的陷阱(如果已设置)将在shell退出之前执行.此选项分别适用于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秒才能停止.

请注意,shell命令状shift,并set --,你可以改变的价值"$@".例如,这是脚本的一小部分,/bin/sh -c "..."如果您使用docker的shell语法,则会从命令中删除该命令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 "$@"
Run Code Online (Sandbox Code Playgroud)