简体   繁体   English

前置子流程控制台输出

[英]Prepend child process console output

I have an app that spawns a child process. 我有一个产生子进程的应用程序。 That child process outputs information about what it's doing by printing to stdout. 该子进程通过打印到stdout输出有关其操作的信息。 The parent process does the same (ie prints to stdout). 父进程执行相同的操作(即打印到stdout)。

In the child process I can write to stdout with some text prepended, but I have to add that to every single location I print across many source files. 在子进程中,我可以写一些标准的文本到stdout,但是我必须将其添加到我在许多源文件中打印的每个位置。

I thought it might be smarter to have the parent process prepend output from the child process that it forks/exec's. 我认为让父进程优先于它派生/执行的子进程的输出优先。 I don't want to redirect the output because seeing the output inline with the parent process is beneficial. 我不想重定向输出,因为看到与父进程内联的输出是有益的。 How do I do this? 我该怎么做呢? I'm using fork/exec in the parent. 我在父级中使用fork / exec。

Do I have to read the output and prepend each line manually or is there a simpler approach? 我是否必须读取输出并手动在每行之前添加,还是有一种更简单的方法?


Update: 更新:

Thanks to Barmar. 感谢Barmar。 Here is how I'm doing it. 这就是我的做法。 I also could read byte by byte in the parent process from the pipe until line end. 我还可以从管道直到行尾在父进程中逐字节读取。 But I chose not to use that approach for reasons of complexity in my single threaded lua+C app. 但是由于单线程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;
}

I thought it might be smarter to have the parent process prepend output from the child process. 我认为让父进程优先于子进程的输出可能更聪明。

I guess it depends on how you judge "smart". 我想这取决于您如何判断“智能”。 It might be simpler to just make the child prepend the desired text to its outputs. 仅使子级将所需的文本添加到其输出中可能会更简单

I don't want to redirect the output because seeing the output inline with the parent process is beneficial. 我不想重定向输出,因为看到与父进程内联的输出是有益的。 What's the best way to do this? 最好的方法是什么?

When two processes share an open file, both access it independently, regardless of the nature of the relationship between those processes. 当两个进程共享一个打开的文件时,无论这些进程之间的关系的性质如何,都可以独立地访问它。 Thus, if your child inherits the parent's stdout , the parent has no mechanism even to notice that the child is sending output, much less to modify that output. 因此,如果您的孩子继承了父级的stdout ,则父级甚至没有机制可以注意到孩子正在发送输出,更不用说修改该输出了。

If you want the parent to handle this, you would need to pass the child's output through the parent. 如果您希望父母处理此问题,则需要将孩子的输出传递给父母。 You could do that by creating a pipe, and associating the child's stdout with the write end of that pipe. 您可以通过创建管道并将该子stdoutstdout与该管道的写入端相关联来实现。 The parent would then need to monitor the read end, and forward suitably-modified outputs to its own stdout . 然后,父级将需要监视读取端,并将经过适当修改的输出转发到其自己的stdout The parent would probably want to create a separate thread for that purpose. 父级可能会为此目的创建一个单独的线程。

Additionally, if the child sometimes produces multi-line outputs that you want prefixed as a group, rather than per-line, then you'd probably need to build and use some kind of protocol for demarcating message boundaries, which would make the whole parent-moderation idea pretty pointless. 此外,如果孩子有时会生成您希望作为一组而不是每行作为前缀的多行输出,那么您可能需要构建并使用某种协议来划分消息边界,这将使整个父级适度的想法毫无意义。

You could create a second child process that performs 您可以创建第二个子进程来执行

execlp("sed", "sed", "s/^/PREFIX: /", (char *)NULL);

Connect the first child's stdout to this process's stdin with a pipe. 用管道将第一个孩子的标准输出连接到该进程的标准输入。

Couldn't you define #define printf(a) printf("your text:" a). 您无法定义#define printf(a) printf("your text:" a).

Other alternative I can think of is using dup 我能想到的其他选择是使用dup

You open the same log file in your child process and dup your stdout to new file descriptor. 你在你的子进程,并打开同一个日志文件dup你的stdout到新的文件描述符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM