【问题标题】:Get pre-shebang executable path in MacOS (equivalent to getauxval(AT_EXECFN) )在 MacOS 中获取 pre-shebang 可执行路径(相当于 getauxval(AT_EXECFN) )
【发布时间】:2021-09-15 05:12:17
【问题描述】:

对于bash - Detect if a script is being run via shebang or was specified as a command line argument - Unix & Linux Stack Exchange 中描述的问题,我们需要区分脚本是通过shebang 运行的情况和作为解释器的参数的情况。

An answer to that question 建议使用 getauxval(AT_EXECFN) 获取 pre-shebang 可执行文件名称——这可行,但仅适用于 Linux。

由于 Pyenv 项目也正式支持 MacOS,如果我们要考虑该解决方案,我们需要一个等效的。


我已经检查了Finding current executable's path without /proc/self/exe——但_dyld_get_image_name(0)_NSGetExecutablePath 都给出了post-shebang 名称。这是我用来检查的示例程序(请参阅上面的问题链接了解它的使用方式;它的编译结果需要代替该问题中给出的python3 Bash 脚本):

#include <stdio.h>
#include <unistd.h>
/*#include <sys/auxv.h>*/
#include <mach-o/dyld.h>
#include <sys/param.h>
#include <alloca.h>

int main(int argc, char** argv) {
        //char *at_execfn = (char*)getauxval(AT_EXECFN);
        //const char *at_execfn = _dyld_get_image_name(0);
        char *at_execfn = (char*)alloca(MAXPATHLEN);
        uint32_t at_execfn_len = MAXPATHLEN;
        _NSGetExecutablePath(at_execfn,&at_execfn_len);          
        printf("original executable: '%s'\n",at_execfn);
        for(int i=0; i<argc; i++) {
                printf("'%s'\n",argv[i]);
        }
        execvp("python3",argv);
}

【问题讨论】:

  • 如果您可以更改脚本,为什么不使用env 调用程序来检测shell 脚本是“调用sh​​ebang”还是“加载了解释器”? #!/usr/bin/env -S SHEBANG=1 "shell"shebang 之类的东西?
  • @Zilog80 我们无法更改用户 Python 脚本中的 shebangs。请参阅链接的问题。

标签: c macos shebang


【解决方案1】:

此答案基于以下假设;我相信其他人会审查它们是否真实,但据我了解,它们是:

  1. Python 脚本只有在直接执行时才会使用 shebang。
  2. 否则,第一个命令行参数将始终为 pythonpython3 或其他一些变体(python3.x 等)。

你已经可以得到原始文件的路径,这很好,因为你可以阅读shebang 说的,但是你还不知道shebang是否被使用,对吧? Python 3.10 提供了一个吸引人的解决方案:sys.orig_argv,其中包括所有命令行参数,而不仅仅是像普通的sys.argv 那样来自程序名称的那些。

但是,我确信您不会在 pyenv 中实现 3.10 独有的功能!如果是这种情况,您可以查看较旧的 C-API Py_GetArgcArgv,其文档简单说明:

在 Python 修改它们之前获取原始命令行参数。

无论哪种方式,我认为拥有文件路径以便您可以阅读 shebang 是难题的第一部分。第二部分是弄清楚是否实际使用了 shebang,我认为答案在大多数情况下都在命令行参数中。

【讨论】:

  • 我们需要在python 可执行替代品中进行检测(目前是用 Bash 编写的——但可以用已编译的程序替换它),而不是在 Python 代码中。
  • 另外,第一个命令行参数总是python*在后shebang命令行中。
最近更新 更多