我注意到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
是什么?
答案 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秒才能停止。
请注意,对于shift
和set --
等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 "$@"