前置子进程控制台输出

时间:2016-09-28 20:37:32

标签: c linux

我有一个应用程序可以生成子进程。该子进程通过打印到stdout输出有关它正在做什么的信息。父进程执行相同的操作(即打印到stdout)。

在子进程中,我可以使用前面的文本写入stdout,但是我必须将其添加到我在多个源文件中打印的每个位置。

我认为让父进程在子进程中添加forforks / exec的输出可能会更聪明。我不想重定向输出,因为看到与父进程内联的输出是有益的。我该怎么做呢?我在父母中使用fork / exec。

我是否必须手动读取输出并预先添加每一行或者是否有更简单的方法?

更新

感谢Barmar。我正是这样做的。我也可以在父进程中逐个字节地从管道读取直到行结束。但我在单线程lua + C应用程序中选择不使用该方法是出于复杂性的原因。

// Crude example of output filtering using sed to 
// prepend child process output text

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <libgen.h>
#include <string.h>


pid_t spawn(int fd[2], const char* path)
{
  printf("Create child\n");
  pid_t pid = fork();
  switch(pid){
    case -1:
      printf("Create process failed");
      return -1;
    case 0:
      dup2(fd[1], STDOUT_FILENO);
      close(fd[0]);
      close(fd[1]);
      execl(path, path, NULL);
      return 0;
    default:
      return pid;
  }
}

pid_t spawnOutputFilter(int fd[2])
{
  printf("Create sed\n");
  pid_t pid = fork();
  switch(pid){
    case -1:
      printf("Create sed failed");
      return -1;
    case 0:
      dup2(fd[0], STDIN_FILENO);
      close(fd[0]);
      close(fd[1]);
      execlp("sed", "sed", "s/^/Engine: /", (char *)NULL);
      return -1;
    default:
      return pid;
  }
}


int main(int argc, char* argv[])
{
  if (argc > 1){
    int options;
    int fd[2];
    pipe(fd);
    pid_t pid = spawn(fd, argv[1]);
    pid_t sed_pid = spawnOutputFilter(fd);

    close(fd[0]);
    close(fd[1]);
    waitpid(pid, NULL, 0);
    waitpid(sed_pid, NULL, 0);
  }

  return 0;
}

3 个答案:

答案 0 :(得分:2)

  

我认为让父进程在子进程之前添加输出可能更聪明。

我想这取决于你如何判断&#34; smart&#34;。可能更简单只是让孩子将所需的文本添加到其输出中。

  

我不想重定向输出,因为查看与父进程内联的输出是有益的。最好的方法是什么?

当两个进程共享一个打开的文件时,无论这些进程之间的关系性质如何,它们都会独立访问它。因此,如果您的孩子继承父stdout,父母甚至没有机制注意到孩子正在发送输出,更不用说修改输出了。

如果您希望父级处理此问题,您需要通过父级传递子级的输出。您可以通过创建管道并将子级stdout与该管道的写入端相关联来实现。然后,父母需要监视读取结束,并将适当修改的输出转发给它自己的stdout。父母可能想要为此目的创建一个单独的线程。

此外,如果孩子有时会产生多行输出,你想要作为一组而不是每行作为前缀,那么你可能需要构建和使用某种协议来划分消息边界,会使整个父母节制的想法毫无意义。

答案 1 :(得分:2)

您可以创建执行

的第二个子进程
execlp("sed", "sed", "s/^/PREFIX: /", (char *)NULL);

用管道将第一个孩子的标准输出连接到此过程的标准输入。

答案 2 :(得分:0)

无法定义common: welcome: "Bienvenido a mi pagina" email: "Correo electronico" bye: "Adios"

我能想到的其他选择是使用dup

您在子进程中打开相同的日志文件,并将#define printf(a) printf("your text:" a). dup打开到新文件描述符。