bash - 当我运行 `sh -c "command"` 时,是否创建了一个子 shell,一个新的 shell 还是这些都没有?

标签 bash command-line

在 bash 中,当我运行以下命令时:

sh -c "<em>command</em>"

是否创建了一个子 shell 然后是 <em>command</em>执行了吗?

我的猜测是该命令将在当前 shell 中运行,但我不确定。这个猜测来 self 已经使用以下命令进行测试的事实:

echo $BASHPID, $BASH_SUBSHELL

sh -c "echo $BASHPID, $BASH_SUBSHELL"

结果是一样的。但正如有人告诉我的那样,这可能有点误导,因为变量可能会在命令执行之前被替换。这是真的吗?

最佳答案

我认为通过示例可以了解情况
(在我的例子中,sh 是指向 /bin/dash 的符号链接(symbolic link))。
我为 sh 做了这个测试:

echo $$ ; sh -c 'echo $$ ; sh -c '"'"'echo $$'"'"' '
16102
7569
7570

三个不同的PID,三个不同的shell。 (如果有不同的 shell,则不会产生 subshel​​l)。


对于 BASH

类似的方式
echo $$ $BASHPID, $BASH_SUBSHELL ; bash -c 'echo $$  $BASHPID $BASH_SUBSHELL  ; bash -c '"'"'echo  $$ $BASHPID $BASH_SUBSHELL '"'"' '
16102 16102, 0
10337 10337 0
10338 10338 0

三个不同的$BASHPID 没有不同的$BASH_SUBSHELL($$$BASHPID 的区别见下面注释>).
如果我们在不需要重新初始化的 子 shell 中,则 $$$BASHPID 应该不同。
同样,$BASH_SUBSHELL 不会递增,它始终为 0。 所以 2 条线索再次表明没有生成新的 subshel​​l,我们只有新的 shell


man bash(4.2.45(1)-release)中,我报告了一些关于何时生成 subshel​​l 的相关部分:

  1. 管道中的每个命令都作为一个单独的进程执行 (即,在 subshel​​l 中)。

  2. 如果命令被控制操作符&终止,shell执行 命令在子 shell 的后台运行。 shell 不会等待 命令结束,返回状态为0。

    命令以 ; 分隔顺序执行;外壳等待每个 命令依次终止。返回状态为上一个的退出状态 命令执行。 ...

  3. ( list ) list在subshel​​l环境中执行
    { 列表; } list 只是在当前的 shell 环境中执行。

  4. coprocess 是一个以 coproc 保留字开头的 shell 命令。协同进程在子shell...

  5. 中异步执行
  6. $ 扩展为 shell 的进程 ID。在 () subshel​​l 中,它扩展为 当前 shell 的进程 ID,而不是 subshel​​l

注意事项:

  • BASHPID 扩展为当前 bash 进程的进程 ID。这不同于 $$ 在某些情况下,例如不需要 bash 的子 shell 重新初始化。
  • BASH_SUBSHELL 每次生成子 shell 或子 shell 环境时递增 1。初始值为0。

  • 对于单引号''和双引号""的使用区别you can see this question .让我们只记住,如果您在双引号"" 中编写命令,变量将通过原始 shell 的参数扩展进行评估,如果 extquote 已启用,因为它默认来自 shopt(cfr. 4.3.2 The shopt builtin in the Bash Reference Manual)

    *extquote* If set, $'string' and $"string" quoting is performed within ${parameter} expansions enclosed in double quotes. This option is enabled by default.

您可能会发现有用的进一步引用,例如

关于bash - 当我运行 `sh -c "command"` 时,是否创建了一个子 shell,一个新的 shell 还是这些都没有?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23951346/

相关文章:

bash - passwd:当我运行我创建的 Bash 脚本时,Debian 上出现无法识别的选项 '--stdin' 错误

bash - sed 脚本 - 临时文件的权限被拒绝

json - 在 shell 中解析 JSON

java - 在命令行上运行模块会出现错误 : Module target not found

command-line - 如何通过命令行为 iOS 开发安装开发人员证书/私钥和配置文件?

java - "java: No match."是什么意思?

regex - 使用 bash 仅匹配第一段

Android SH 外壳脚本

iphone - 通过命令行将 IPA 推送到设备(在 xcodebuild 之后)?

java - Ant API Commandline.Argument 类中 setLine() 和 setValue() 之间的区别?