什么是 shell 表单和 exec 表单?

What are shell form and exec form?

什么是 shell 形式和 exec 形式的命令?
我已经阅读了几个文档以清楚地了解 shell 表单和 exec 表单。但一切都让我感到困惑。谁能帮忙弄清楚这两种形式有什么区别?

PS:虽然我在阅读 docker 文件说明 (ex: RUN, CMD, ENTRYPOINT) 时遇到了这些术语,但我想知道它们之间的区别他们一般来说,而不是在 docker 上下文中。

docker shell 语法(它只是一个字符串,如 RUNENTRYPOINTCMD)将 运行该字符串作为 /bin/sh -c 的参数。这为您提供了 shell 来扩展变量、子命令、管道输出、将命令链接在一起以及其他 shell 便利。

RUN ls * | grep $trigger_filename || echo file missing && exit 1

exec 语法只是 运行 您提供的二进制文件和您包含的参数,但没有 shell 解析的任何功能。在 docker 中,您使用 json 格式的数组来表示。

RUN ["/bin/app", "arg1", "arg2"]

exec 语法的优点是从启动的进程中删除 shell,这可能会抑制信号处理。在 shell 语法中使用 /bin/sh -c 重新格式化命令也可能会破坏入口点和 cmd 的连接。

entrypoint documentation 很好地涵盖了各种场景并对此进行了更详细的解释。

These following explanation are from the Kubernetes In Action book(chapter 7).

首先,它们有两种不同的形式:

  • shell form—For example, ENTRYPOINT node app.js

  • exec form—For example, ENTRYPOINT ["node","app.js"]

其实区别是指定的命令是否在shell内部调用。我也想用一个例子来解释它们之间的主要区别。

ENTRYPOINT ["node", "app.js"]

这直接运行节点进程(不在 shell 内),如您在容器内列出进程 运行 所见:

$ docker exec 4675d ps x  
PID TTY      STAT   TIME    COMMAND
1    ?        Ssl    0:00   node app.js   
12   ?        Rs     0:00   ps x

ENTRYPOINT node app.js

如果您使用 shell 形式(ENTRYPOINT 节点 app.js),这些将是容器的进程:

$ docker exec -it e4bad ps x  
PID TTY      STAT   TIME    COMMAND    
1    ?        Ss     0:00   /bin/sh -c node app.js
7    ?        Sl     0:00   node app.js   
13   ?        Rs+    0:00   ps x

如您所见,在这种情况下,主进程(PID 1)将是 shell 进程,而不是节点进程。节点进程(PID 7)将从 shell 开始。 shell 过程是不必要的,这就是为什么你应该始终使用 ENTRYPOINT 指令的 exec 形式。

扩展

的答案

这些是每条指令使用的推荐形式:

RUN: shell form, because of the shell features described in the below source

ENTRYPOINT: exec form, because of the signal trapping described in the below source

CMD: exec form, because of the signal trapping described in the below source

Shell 特征、变量替换、信号捕获和转发、命令和入口点连接 在下面的例子中解释 link.

在这个非常好的博客中有更多内容:source