以下代码成功列出了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)
仅根据版本号判断(这可能是不正确的做法),旧版本可以正确打印输出,而新版本则不能?
答案 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
或任何其他外壳无关。