为什么使用“/bin/bash -c $command”而不是直接调用“$command”?

Why use "/bin/bash -c $command" instead of calling "$command" directly?

经常,我遇到用 /bin/bash -c/bin/sh -c 而不是直接执行的命令。例如,不是 cp /tmp/file1 /tmp/file2,而是 /bin/bash -c "cp /tmp/file1 /tmp/file2".

这样做而不是直接执行命令的原因有哪些?在最近的记忆中,我在 Docker 和 K8s 命令中看到最多。我唯一能真正想到的是因为你特别想要 运行 具有特定 shell 的命令,但这似乎是一个漂亮的 rare/niche 用例?

Here为具体示例,k8s部署使用:

command: ["/bin/sh"]
args: ["-c", ". /config/dynamicenv.sh && /app/bin/docker-entrypoint server"]

而不是我期望的默认值:

. /config/dynamicenv.sh && /app/bin/docker-entrypoint server

没有具体的例子很难说,但这样做的一个常见原因是你想利用 shell i/o 重定向,管道等。例如,这个片段Kubernetes pod 清单会失败,因为它涉及管道,这需要 shell 来执行命令行:

containers:
  image: docker.io/alpine:latest
  command:
    - echo hello world | sed s/world/container/

但这行得通:

containers:
  image: docker.io/alpine:latest
  command:
    - /bin/sh
    - -c
    - echo hello world | sed s/world/container/

这是一种相对常见的情况,您会看到使用 shell 明确执行的事情。如果您想用一些具体示例更新您的问题,我们可以提供更详尽的答案。


您的示例与我在此处的回答中已经包含的内容非常接近。命令 . /config/dynamicenv.sh && /app/bin/docker-entrypoint server 不是一个简单的命令;这是一个 shell 脚本,同时使用了 .&& 运算符。

如果他们写:

command: [". /config/dynamicenv.sh && /app/bin/docker-entrypoint server"]

它会失败并出现如下错误:

exec: "[\". /config/dynamicenv.sh && /app/bin/docker-entrypoint server\"]": stat [". /config/dynamicenv.sh && /app/bin/docker-entrypoint server"]: no such file or directory: unknown.

命令需要用sh -c包裹才能正确执行。