【问题标题】:linux execvp ; ls cannot access |, No such file or directorylinux 执行程序; ls 无法访问|,没有这样的文件或目录
【发布时间】:2013-09-07 07:54:48
【问题描述】:

我正在尝试编写一个 shell。但是我的 shell 不执行命令 - ls -l |较少的。我正在使用 execvp。代码如下。

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

int main(){
    int pid, status, num, len;
    char str[1000], cwd[100];
    char* word[100];

    getcwd(cwd, sizeof(cwd));

    while(1){
        chdir(cwd);

        printf("%s > ", cwd);

        gets(str);

        pid=vfork();

        if(pid == 0){
            num = 0;
            word[num] = strtok (str, " ");

            while (word[num] != NULL) {
                word[num] = strdup (word[num]);
                len = strlen (word[num]);
                if (strlen (word[num]) > 0)
                    if (word[num][len-1] == '\n')
                        word[num][len-1] = '\0';
                word[++num] = strtok (NULL, " ");
            }

            if(strcmp(word[0], "cd") == 0){
                chdir(word[1]);
                getcwd(cwd, sizeof(cwd));
            }
            else{
                execvp(word[0],word);
            }

            exit(0);
        }
        else{
            wait(&status);
        }
    }

    return 0;
}

【问题讨论】:

  • 据我所知, | 是一个与 shell 相关的令牌。在 shell 之外做这件事并没有真正起作用,因为它的 shell 读取 | 并让魔法发生。没有外壳来实现神奇的管道......它不起作用。
  • 那么我还有其他方法可以运行|吗?我可以以某种方式将字符串和蛮力使它工作
  • @Cornstalks 说得真切。 execvp 用于执行带有一组参数的命令(如果需要)。你可以试试system 来调用一个成熟的shell命令行。
  • 在您使用vfork() 之前,请阅读您可以在子进程中执行的操作。我不认为chdir()getpwd() 是允许的。请改用fork()。这可能不是你的主要问题(目前),但要非常非常小心vfork() 的限制。

标签: c linux shell exec systems-programming


【解决方案1】:

ls -l | less实际上是一个shell命令行,由两个通过管道连接的进程组成。 execvp() 调用只能产生一个进程。

如果您想从您的程序中执行此操作,您必须显式调用 shell - 通过使用 system() 调用或将命令行更改为 sh -c 'ls -l | less'。您的 word 数组应如下所示:

word[0] = "sh"
word[1] = "-c"
word[2] = "ls -l | less"
word[3] = NULL

[编辑] 或者,您可以执行 shell 在内部执行的操作:生成两个进程并用管道连接它们。这将涉及使用fork()pipe()dup2()execve() 调用。但是,调用 shell 的工作量要少得多,而且由于 less 无论如何都是一个交互式程序,所以您不必担心性能问题:任何花费少于 100 毫秒的东西都被认为是瞬时的。

【讨论】:

  • +1 只是为了滥用 sh 作为 execvp 命令。没看到=P。
  • @WhozCraig:GNU libc system() 在内部做着完全相同的事情。见:sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/…
  • @KrzysztofKosiński 这太棒了。我不知道。谢谢!
  • popen() 或许也有帮助。
  • 使用系统外壳编写外壳(通过systempopen 或执行/bin/sh)并不完全符合作业的目标.....
猜你喜欢
  • 2016-02-26
  • 2019-03-31
  • 1970-01-01
  • 1970-01-01
  • 2017-02-10
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多