我最近在很多docker-entrypoint.sh
脚本中都看到了这一点,但在网上找不到解释。我的第一个想法是这与信号有关,但这是一个非常疯狂的猜测。
答案1
该"$@"
位将扩展到位置参数列表(通常是命令行参数),单独引用以避免分词和文件名生成(“通配符”)。
将exec
用执行其参数所产生的进程替换当前进程。
简而言之,exec "$@"
将以当前进程被替换的方式运行命令行参数给出的命令(如果能够exec
执行该命令)。
答案2
二 其他答案解释了什么exec "$@"
。Stack Overflow 上的这个答案解释了为什么它对 Docker 很重要,正如您猜测的那样,它确实与信号有关:
这在 Docker 中对于正确代理信号非常重要。例如,如果 Redis 在没有 的情况下启动
exec
,它将不会收到SIGTERM
ondocker stop
,也不会有机会彻底关闭。在某些情况下,这可能会导致数据丢失或僵尸进程。如果您确实启动了子进程(即不使用
exec
),则父进程将负责适当地处理和转发信号。这是supervisord
在容器中运行多个进程时最好使用或类似的原因之一,因为它将适当地转发信号。
答案3
"$@"
在类似 Bourne 的 shell 中,列表上下文中会扩展为所有位置参数作为单独的参数。
在脚本中,最初,位置参数是脚本本身接收的参数。
exec
是在与 shell 相同的进程中运行命令。这是脚本将执行的最后一个命令,因为此后,进程将运行 shell 之外的另一个命令。
所以如果你的脚本是
#! /bin/sh -
exec "$@"
然后您使用 shell 命令行调用脚本,例如:
/path/to/your-script 'echo' "some test" 'x y'
它将exec
使用echo
、some test
和作为参数调用,这些参数将在之前运行 shell 的同一进程中x y
执行echo
(在大多数sh
实现中,/bin/echo
而不是shell 内置),并使用和作为参数解释脚本。echo
some test
x y