`exec "$@"` 有什么作用?

Joh*_*ann 16 linux bash shell-script exec

我最近在很多docker-entrypoint.sh脚本中都看到了这一点,并且在网上找不到解释。我的第一个想法是它与信号有关,但这是一个非常疯狂的猜测。

Kus*_*nda 7

"$@"位将扩展到位置参数列表(通常是命令行参数),单独引用以避免分词和文件名生成(“globbing”)。

exec将与从执行它的参数而产生的过程替换当前过程。

简而言之,exec "$@"将以当前进程被它替换的方式运行命令行参数给出的命令(如果exec能够执行该命令)。


Ste*_*itt 6

两个 其他的答案解释什么exec "$@"呢。Stack Overflow 上的这个答案解释了为什么它对 Docker 很重要,正如您猜测的那样,它确实与信号有关:

这在 Docker 中对于正确代理信号很重要。例如,如果 Redis 是在没有 的情况下启动的exec,它将不会收到SIGTERMondocker stop并且不会有机会干净地关闭。在某些情况下,这可能会导致数据丢失或僵尸进程。

如果您确实启动了子进程(即不使用exec),则父进程将负责处理和转发适当的信号。这是supervisord在容器中运行多个进程时最好使用或类似的原因之一,因为它会适当地转发信号。


Sté*_*las 5

"$@" 在类似 Bourne 的 shell 中,在列表上下文中将所有位置参数扩展为单独的参数。

在脚本中,位置参数最初是脚本本身收到的参数。

exec是在与 shell 相同的进程中运行命令。这是脚本将执行的最后一个命令,因为在那之后,该进程将运行另一个命令而不是 shell。

所以如果你的脚本是

#! /bin/sh -
exec "$@"
Run Code Online (Sandbox Code Playgroud)

并且您使用 shell 命令行调用您的脚本,例如:

/path/to/your-script 'echo' "some  test" 'x y'
Run Code Online (Sandbox Code Playgroud)

它将exec使用echo, some test, 和x y作为参数调用,这些参数将echo在之前运行 shell 的同一进程中执行(在大多数sh实现中,/bin/echo而不是echoshell 内置),并用some testx y作为参数解释您的脚本。