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

时间:2016-08-22 14:57:08

标签: shell docker

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

# file1    
import time
x = 0
while True:
    x += 1
    time.sleep(2.0)

# file2
from file1 import x
print x

#!/bin/bash set -e ... code ... exec "$@" set -e是什么?

3 个答案:

答案 0 :(得分:49)

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

见:

答案 1 :(得分:23)

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

exec "$@" - 将重定向输入变量,请参阅更多here

答案 2 :(得分:18)

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

  

set -e:

     

如果管道(可能包含单个简单命令),列表或复合命令,则立即退出(请参阅SHELL   上面的GRAMMAR),以非零状态退出。 shell不会退出   如果失败的命令立即成为命令列表的一部分   跟随一段时间或直到关键字,在if之后的部分测试   或者elif保留字,是&&amp ;;中执行的任何命令的一部分。或||   列表除了最后一个&&之后的命令或者||,任何   管道中的命令但是最后一个,或者命令的返回值   正在被倒置!如果是子shell以外的复合命令   返回非零状态,因为命令在-e存在时失败   忽略,shell不退出。 ERR上的陷阱(如果已设置)将被执行   在shell退出之前。此选项适用于shell环境   和每个子shell环境分开(参见COMMAND EXECUTION   上面的环境),并可能导致子壳在执行之前退出   子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 "..."使用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 "$@"