在空环境中,如何找到可执行文件?

在空环境中,如何找到可执行文件?

出于实验目的,我创建了一个打印$PATH, 并调用的二进制文件which,如下所示:

#include <stdlib.h>
#include <stdio.h>

int main() {
    char *path = getenv("PATH");

    if (path)
        printf("got a path: %s\n", path);
    else
        printf("got no path\n");

    system("which which");
    return 0;
}

当我在空环境中运行它时

env -i ./printpath

我得到以下打印输出:

got no path
/usr/bin/which

我的问题是:which即使没有,为什么会调用正确的二进制文件$PATH

答案1

您已经使用了systemfunction,因此它将使用另一个 shell 来运行该命令which which。从man system

DESCRIPTION
       system()  executes a command specified in command by calling /bin/sh -c
       command, and returns after the command has been completed.  During exe‐
       cution  of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT
       will be ignored.

如果将which which命令更改为echo $PATH

$ env -i ./a.out 
got no path
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

如果您将代码更改为使用execve而不是system,您将获得预期的输出:

#include <stdlib.h>                                                             
#include <stdio.h>  

int main() {                                                                    
    char *path = getenv("PATH");                                                

    if (path)                                                                   
        printf("got a path: %s\n", path);                                       
    else                                                                        
        printf("got no path\n");                                                

    execve("echo $PATH");                                                       
    return 0;                                                                   
} 

编译并运行它:

$ gcc test.c && env -i ./a.out 
got no path

答案2

在空环境中,除非指定完整路径,否则找不到可执行文件。尝试一下execvp

system函数调用一个 shell——在使用 Glibc 的 Linux 上,它会调用/bin/sh(所以PATH不需要)。除了来自环境的变量之外,Shell 还定义了一些自己的变量。您可以通过运行查看它们定义的内容env -i /path/to/shell -c set,以及通过运行导出的内容env -i /path/to/shell -c export。特别是,dash 和 bash(您可能会在 Linux 上找到的两种 shell)如果环境中没有,则/bin/sh设置(但不导出)为“正常”默认值。PATH不同的 shell 设置不同的值或根本不设置。

$ env -i bash -c 'echo $PATH'
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ env -i dash -c 'echo $PATH'
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ env -i mksh -c 'echo $PATH'
/usr/bin:/bin
$ env -i ksh93 -c 'echo $PATH'

$ env -i zsh -c 'echo $PATH' 
/bin:/usr/bin:/usr/ucb:/usr/local/bin
$ env -i csh -c 'echo $PATH' 
PATH: Undefined variable.
$ env -i tcsh -c 'echo $PATH'
PATH: Undefined variable.

在我的机器上(显然也是你的机器上),which它本身就是一个/bin/sh脚本。调用的 shellsystem使用自己的路径变量来查找which程序,但不导出它。运行脚本本身的 shellwhich也定义了PATH供其内部使用的变量。

相关内容