【问题标题】:Pipe two shell commands in C在 C 中管道两个 shell 命令
【发布时间】:2019-07-28 16:05:39
【问题描述】:

我正在尝试通过 C 中的程序执行 grep -o colour colourfile.txt | wc -w > newfile.txt,而不是使用命令行。

这是我目前所拥有的:

#include <stdlib.h>
#include <unistd.h>

int main (void) {
    int fd[2];

    pipe(fd);

    if (fork()) {
        // Child process
        dup2(fd[0], 0); // wc reads from the pipe
        close(fd[0]);
        close(fd[1]);
        execlp("wc", "wc", "-w", ">", "newfile.txt", NULL);
    } else {
        // Parent process
        dup2(fd[1], 1); // grep writes to the pipe
        close(fd[0]);
        close(fd[1]);
        execlp("grep", "grep", "-o", "colour", "colourfile.txt", NULL);
    }
    exit(EXIT_FAILURE);
}

【问题讨论】:

  • 你没有具体提到你的问题在哪里,什么不起作用等等。
  • &gt; 是对 shell 的指令,而不是 wc 的参数;它告诉 shellexec*-family 调用之前打开newfile.txt 进行写入,并告诉dup2() 将其转到FD 1。因此,您也需要自己实现该逻辑。
  • 就像管道运算符(|)是由shell实现的,输出重定向运算符&gt;也是如此。要模拟您提供的 shell 命令,您的程序也必须实现后者。
  • 建议了解函数:popen() 及其应用

标签: c shell pipe fork


【解决方案1】:
  1. if (fork()) { 表示 parent process 不是 child process,参见 http://man7.org/linux/man-pages/man2/fork.2.html
  2. 你应该处理&gt; 就像| 使用open()

以下code 可以工作:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>

int main (void) {
  int pipefd[2];
  pipe(pipefd);

  if (fork()) {
    // Child process
    dup2(pipefd[0], 0); // wc reads from the pipe
    close(pipefd[0]);
    close(pipefd[1]);
    int fd = open("newfile.txt", O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR);
    dup2(fd, 1);
    close(fd);
    execlp("wc", "wc", "-w", NULL);
  } else {
    // Parent process
    dup2(pipefd[1], 1); // grep writes to the pipe
    close(pipefd[0]);
    close(pipefd[1]);
    execlp("grep", "grep", "-o", "colour", "colourfile.txt", NULL);
  }
  exit(EXIT_FAILURE);
}

【讨论】:

  • 还有一个小细节:如果fork() 返回负数,OP 可能会发出错误消息并失败,而不是生成没有错误的空输出文件。
  • 这三行是​​邪恶的:int fd = open("newfile.txt", O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR); dup2(fd, 1); close(fd);——你之前将fd定义为2个int的数组;现在您将其重新定义为单个int(在您已经使用过数组变体的块中)。这太恶心了。我强烈建议对其中一个变量使用不同的名称。如果execlp() 调用中的一个或两个失败,报告执行失败的内容将是礼貌的。
猜你喜欢
  • 2020-07-03
  • 1970-01-01
  • 1970-01-01
  • 2011-12-26
  • 1970-01-01
  • 2017-06-03
相关资源
最近更新 更多