【问题标题】:Take output of bash command and pass it as command line argument to a c executable (pipes)获取 bash 命令的输出并将其作为命令行参数传递给 c 可执行文件(管道)
【发布时间】:2018-12-04 18:09:54
【问题描述】:

我正在尝试在 c 中创建一个自定义 shell,当我运行时

密码 | ./显示

它将获取 pwd 输出并将其作为 ./show 的命令行参数传递,并且必须使用管道。

我已经阅读了我能找到的任何相关问题,但我无法让它发挥作用。

到目前为止,我认为我已成功将输出引导到管道中,但我不知道如何将其传递给 ./show。我一直在打印它只是为了验证它是否能通过管道。

        if(option == 2){

        getArgs(&A,args,directory,&size);

        pipe(fd);
        pid = fork();

        if(!pid){
            dup2(fd[1],STDOUT_FILENO); //output into pipe
            close(fd[0]);
            close(fd[1]);

            com=args[0];
            for(i=1;i<(size-2);i++){
              com=concat(com," ");
              com=concat(com,args[i]);
            }

            readCommand(args,directory,com,(size-1));
            return 1;
        }

        close(fd[1]);

        int nbytes = read(fd[0], foo, sizeof(foo));
        printf("Output: (%.*s)\n", nbytes, foo);

    }

exec 发生在 readCommand 内部,所以它在这里

      void readCommand(char *args[10],char *directory,char *com, int i){

    if(execl(directory, args[i],args[i+1], NULL)==-1){
        execl("/bin/sh", "/bin/sh", "-c", com, NULL);
        perror("execlp");
    }
    else{
        execl(directory, args[0],args[1],args[2],args[3],args[4], NULL); //max number of args=4
        perror("execlp");
    }
  }

我之前尝试过让它与两个分叉一起工作,但后来我不确定我的输出重定向是否正确,而且它似乎更难失败。如果有帮助,我也可以包含该代码。

感谢您的帮助,我的最后期限是几个小时后...

更新:阅读答案后我更新了代码

if(option == 2){

        getArgs(&A,args,directory,&size);

        pipe(fd);

        if (!fork()) {
            pipe(fd);

            if(!fork()) {

                dup2(fd[1], 1);
                close(fd[0]);
                close(fd[1]);

                execlp(args[0], args[0], NULL);
            }
            else {

                dup2(fd[0], 0);
                close(fd[0]);
                close(fd[1]);

                execlp(args[size-1], args[size-1], NULL);
            }
        }
        wait(NULL);
    }

现在我打印了一个空行,然后提示输入新命令。

【问题讨论】:

    标签: c shell redirect pipe output


    【解决方案1】:

    您需要分叉两个进程,它们之间有一个管道。您的 shell 不应尝试读取或写入管道。

    这是一个完整的示例,它对您的管道进行硬编码以演示如何设置它:

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/wait.h>
    
    int main() {
      char* producer="pwd";
      char* consumer="./show";
      int fds[2];
    
      printf("Going to run the equivalent of '%s | %s'\n", producer, consumer);
      // Create a child that will become the consumer
      if (!fork()) {
        pipe(fds);
        // Create another child to be the producer
        if(!fork()) {
          // Set up stdout to be the pipe
          dup2(fds[1], 1);
          close(fds[0]);
          close(fds[1]);
          // Execute the producer
          execlp(producer, producer, NULL);
        } else {
          // Set up stdin to be the pipe
          dup2(fds[0], 0);
          close(fds[0]);
          close(fds[1]);
          // Execute the consumer
          execlp(consumer, consumer, NULL);
        }
      }
      // Wait for the consumer to finish
      wait(NULL);
      printf("The pipeline is done, the \"shell\" is exiting\n");
    }
    

    这是show的一个实现:

    #!/bin/sh
    echo "Here's the data $0 read: $(cat)"
    

    这是一个真实外壳的结果:

    $ pwd
    /tmp
    
    $ pwd | ./show
    Here's the data ./show read: /tmp
    

    这是运行此示例时的结果:

    $ gcc foo.c -o foo && ./foo
    Going to run the equivalent of 'pwd | ./show'
    Here's the data ./show read: /tmp
    The pipeline is done, the "shell" is exiting
    

    【讨论】:

    • 使用你的代码我改进了我的两个分叉实现......仍然不起作用,你能看看更新吗?
    • 该示例有效,您可以对其进行测试,因此了解您的不同之处可能会有所帮助。例如,args[0]args[size-1] 包含什么?
    • 生产者和消费者,我把它们打印出来了,它们没问题。我试图运行你的 show 实现,但它没有编译,我得到一个错误 #!,所以我不能用它来测试它。
    • show 是一个shell脚本,不需要编译。你可以把它放在一个名为 show 的文件中并运行 chmod +x show 使其可执行
    • 如果您想尝试找出原因,请尝试提供更多信息。例如:“我尝试将show 复制粘贴到文件中,我成功运行chmod +x show,但是当我从终端尝试pwd | ./show 时,我收到错误bash: ./show: /bin/bash^M: bad interpreter: No such file or directory”而不是预期的消息Here's the data ./show read: /tmp
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-01
    • 2010-11-26
    • 2013-11-21
    • 1970-01-01
    • 1970-01-01
    • 2012-12-21
    相关资源
    最近更新 更多