Python/Dockerfile/Kubernetes 中的 Shell 模式与 Exec 模式
在使用 Python 的 subprocess 包调用其他程序时,或者编写 Dockerfile 时,我们都会遇到一个小问题:使用 shell 模式,还是 Exec 参数化模式?
显然,使用 Shell 模式是最方便的——直接把命令当成一个字符串,一股脑儿传给 subprocess 或者 Dockerfile 中的 CMD 就好了。
如果要使用参数化模式的话,我们还需要自己切分命令。如果切分错误,程序的执行效果很可能会不符合预期。参数化模式还不支持使用 &&
|
这样的 shell 语法。
所以我们应该使用哪一种呢?它们到底有啥区别?很长一段时间内我都不知道。
Shell 模式
Shell 模式,其实就是通过系统的 shell 来执行给定的字符串!所以这种模式下,我们不需要自己切分命令,甚至可以使用 &&
|
>
这些 shell 语法。
Exec 模式
这就是 Python subprocess 中 shell=False,或者 Dockerfile 中使用 EntryPoint+CMD 时,命令被调用的方式,在 Kubernetes 中,这对应 command+args。
这种方式下,subprocess 参数列表中的第一个参数会被当作程序名称,后面所有的参数都会被作为参数传给前述程序。
Dockerfile 也是一样,entrypoint 定义程序名称,CMD 定义程序的参数。
用哪个好
尽量使用 Exec 模式,Shell 模式有被注入的风险,而且 Shell 模式的报错信息也不如 Exec 模式清晰。