从C程序(Ubuntu v / s MacOS)重击内部命令

时间:2018-09-20 06:02:19

标签: c bash macos ubuntu

以下代码成功列出了Ubuntu bash和MacOS bash上当前目录的内容。

int main() {
    char* args[3];
    args[0] = "ls";
    args[1] = NULL;
    args[2] = NULL;
    execvp(args[0], args);
    return 0;
}

以下代码在Ubuntu bash上不打印任何内容,但在MacOS bash上打印ls is /bin/ls

int main() {
    //pid_t pid = fork();
    char * args[3];
    args[0] = "type";
    args[1] = "ls";
    args[2] = NULL;
    //if (!pid) 
    execvp(args[0], args);
    return 0;
}

当我直接在Ubuntu bash上运行type时,它会显示ls is hashed (/bin/ls)

区别在于type是bash内部命令,而ls不是。但是,为什么Ubuntu上的bash行为与MacOS上的bash有所不同?

Ubuntu bash版本:GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)

MacOS bash版本:GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)

仅根据版本号判断(这可能是不正确的做法),旧版本可以正确打印输出,而新版本则不能?

2 个答案:

答案 0 :(得分:4)

您忘记测试console.log是否失败。至少尝试编码:

execvp

可能在您的if (execvp(args[0], args)) { fprintf(stderr, "execvp %s failed: %s\n", args[0], strerror(errno)); exit(EXIT_FAILURE); } 的Ubuntu execvp上失败。也许MacOSX有一些type或您的PATH中有任何东西。

仔细阅读 两个系统上的execvp(3)文档。考虑在Linux上也使用strace(1)来了解发生了什么(对于MacOSX,您可以找到similar thing)。

请注意,/usr/bin/type仅适用于可执行文件(不适用于Shell内置命令)

答案 1 :(得分:1)

您的问题中没有bash。也就是说,该程序的执行与bash没有任何关系。

execvp实际上是一个系统调用,其效果是(如果成功,则不应认为这是理所当然的)用新的过程映像替换当前执行环境,并从文件中加载可执行文件表示为第一个参数。操作系统既不需要也不需要bash来执行程序。

如果要使用bash,则需要要求操作系统运行bash。如果您要运行bash内置命令,这可能会很有用:

char* args[] = { "bash", "-c", "type ls", 0};
execvp(args[0], args);

但是,由于您没有调用bash,因此您依赖于名为type的外部命令实用程序。正是这种效用的存在与否导致了不同的行为。它与bash或任何其他外壳无关。