【问题标题】:Why should one exec "sh -c a.out" instead of a.out itself?为什么一个 exec 应该“sh -c a.out”而不是 a.out 本身?
【发布时间】:2020-10-01 21:19:25
【问题描述】:

我正在研究 Apple 在 https://opensource.apple.com/source/Libc/Libc-167/gen.subproj/popen.c.auto.html 上对 popen() 的实现,并注意到他们使用的是 execl(_PATH_BSHELL, "sh", "-c", command, NULL) 而不是 execl(_PATH_BSHELL, command, NULL)

为什么要(或应该)执行可执行文件,例如a.out 通过sh -c 而不仅仅是可执行文件本身?

如果您执行sh -c a.out 而不仅仅是a.out 本身,那么实际的a.out 进程最终会成为“孙”进程而不是 进程吗?

【问题讨论】:

    标签: c process popen execl


    【解决方案1】:

    为什么要(或应该)执行可执行文件,例如a.out 通过sh -c 而不仅仅是可执行文件本身?

    popen() 旨在运行包含 shell 语法的 shell 命令,例如 > 重定向、| 管道和 && 命令链接。它需要通过sh -c 传递字符串以支持这些构造。如果没有,这些句法特征将作为参数逐字传递给相关程序。

    例如,popen("make clean && make") 应该触发两个 make 调用。如果没有sh -c,它将使用三个参数调用一次make,就好像一个输入过一样

    $ make clean '&&' make
    

    在航站楼。

    如果您执行sh -c a.out 而不仅仅是a.out 本身,那么实际的a.out 进程最终会成为“孙”进程而不是 进程吗?

    是的,没错。在当前进程和a.out之间会有一个sh进程。

    【讨论】:

    • 最后取决于sh 是什么。例如,如果它是 bash 或 zsh,它将在没有分叉的情况下执行(如果命令足够简单的话),所以它最终会成为一个孩子。 Dash 不会这样做,因此如果您使用的系统中 sh 是 dash,它将按照您的指示工作。
    【解决方案2】:

    他们使用execl(_PATH_BSHELL, "sh", "-c", command, NULL) 而不是execl(_PATH_BSHELL, command, NULL)

    后者不会直接执行command,而是_PATH_BSHELL (/bin/sh) 将其$0 设置为command 并且没有参数,从而导致shell 期待命令从它的标准输入。

    此外,该语法依赖于将NULL 定义为显式指针(例如((void*)0)),而不仅仅是0,这在任何地方都无法保证。虽然他们可以在他们的实现中做到这一点(因为他们控制所有的标头),但这不是你应该在应用程序代码中做的。

    不,execl(command, command, (void*)NULL) 也不会直接执行 command,除非 commanda) 完整路径和 b) 在可执行文件中格式(二进制或以 she-bang #! 开头的脚本——后者是 非标准 扩展名)。如果command 是要在PATH 中查找的简单命令名称(如pwda.out)或不是以she-bang 开头的可执行脚本,那么您应该使用execlp 而不是@ 987654340@.

    exec[lv]p[e] 函数做了一些 shell 做的事情(比如查看 PATH),但不是所有的事情(比如运行多个命令或扩展变量):这就是为什么函数像 system(3) 或 @ 987654344@ 将命令传递给/bin/sh -c。请注意,它是 /bin/sh,而不是用户的登录 shell 或所使用环境中的 $SHELL

    如果您执行sh -c a.out 而不仅仅是a.out 本身,那么实际的a.out 进程最终会成为“孙”进程而不是子进程吗?

    仅适用于 dash 等一些 shell。不适用于bashksh93mkshzshyashbusybox 等,它们将直接执行a.out,而不是分叉等待它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-30
      • 2018-05-02
      • 2022-01-25
      • 1970-01-01
      • 1970-01-01
      • 2017-04-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多