什么是shell形式和exec形式?

时间:2017-12-20 11:27:28

标签: shell docker exec

什么是shell形式和exec形式的命令?
我已经通过几个文档来清楚地了解shell形式和exec形式。但所有人看起来都让我感到困惑。任何人都可以帮助弄清楚这两种形式有什么区别?

PS :虽然我在浏览docker文件指令(ex: RUN, CMD, ENTRYPOINT)时遇到过这些术语,但我想知道它们之间的区别,而不是在docker上下文中。

2 个答案:

答案 0 :(得分:10)

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

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

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

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

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

答案 1 :(得分:9)

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

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

  • 外壳形式-例如, ENTRYPOINT节点app.js

  • exec表单-例如, ENTRYPOINT [“ node”,“ app.js”]

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

ENTRYPOINT [“ node”,“ app.js”]

这将直接运行节点进程(不在外壳内部),如列出容器中运行的进程所示:

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

ENTRYPOINT节点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进程是不必要的,这就是为什么您应该始终使用 ENTRYPOINT 指令的exec形式的原因。