使用execve命令的新路径来运行ls命令

3

我正在尝试使用execve命令运行ls命令。目前,我正在使用以下参数运行它:

execve(args[0], args, env_args)
//args looks like {"ls", "-l", "-a", NULL}
//env_args looks like {"PATH=/bin", "USER=me", NULL}

我原本期望这个程序会使用我的新的env_args运行ls命令,也就是说它会在我的PATH中查找ls。但是,实际上,这段代码实际上没有做任何事情。当我运行这段代码时,它只是返回到我的命令提示符而没有任何输出。
使用相同的args[],我用execvp执行ls命令并且成功搜索了当前路径。
你能告诉我我做错了什么吗?
我试图编写自己的shell程序,以便我可以创建和导出自己的环境,并让exec使用我在char**中定义的环境。实质上,我正在编写自己的函数来操作env_args以添加和删除变量,并且当我调用exec时,我希望能够在{"ls", "-l", NULL}上调用exec,并在我的新环境路径变量中查找名为ls的有效程序。我希望这解释了我正在做的事情。我不认为extern environ变量在这种情况下适用于我。
1个回答

11
execve()函数不会查找PATH环境变量,如果需要使用PATH,则需要使用execvp()函数。你的程序无法执行ls,且在execve()之后未报告程序执行失败。请注意,exec *()系列函数的成员仅在出错时返回。

如果将/bin作为当前目录运行程序(因为./ls - 也就是ls - 将存在),则可以获得所期望的结果(或多或少)。

您需要在execve()的第一个参数中提供可执行文件的完整路径名,并使用适当的PATH设置找到它。

或者继续使用execvp(),但是将environ变量设置为新环境。请注意,environ是POSIX全局变量中唯一未在任何头文件中声明的变量。

extern char **environ;

environ = env_args;
execvp(args[0], &args[0]);

你不需要保存旧值并恢复它;因为你正在子进程中,切换其环境不会影响主程序(shell)。


这似乎按照我的期望工作 - 并且证明了原始代码的行为符合我的期望。

#include <stdio.h>
#include <unistd.h>

extern char **environ;

int main(void)
{
    char *args[]     = { "ls", "-l", "-a", NULL };
    char *env_args[] = { "PATH=/bin", "USER=me", NULL };

    execve(args[0], args, env_args);
    fprintf(stderr, "Oops!\n");

    environ = env_args;
    execvp(args[0], &args[0]);
    fprintf(stderr, "Oops again!\n");

    return -1;
}

当我在当前目录创建一个可执行文件ls时,会出现一个“糟糕!”的提示,然后列出我的目录。

#!/bin/sh
echo "Haha!"

那么我就不会收到“糟糕!”而是会得到“哈哈!”。


好的,但是如果我想让execvp查看与环境中定义的不同路径呢?那就是我正在寻找的功能。 - james
转念一想,我觉得environ不是我想要的。我还不确定如何做到这一点。 - james
你为什么认为设置环境不是答案?ls 在你的机器上在哪里找到? - Jonathan Leffler
好的,乔纳森,我认为你是对的。我想我只是误解了execve应该做什么。我以为你可以在新环境中将PATH传递给它。 - james
刚试了一下,看起来我可以让它工作。谢谢! - james

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接