在子进程中重定向STDOUT

Ara*_*rav 6 perl

有一个父进程,它通过fork产生multipe子进程。我希望通过父进程和子进程将日志文件分开。问题是子进程STDOUT被重定向到父日志文件以及子日志文件中。不知道我需要更改以避免子进程日志消息进入父日志文件。我也不能理解下面的setEnvironment函数创建OUT和ERR文件句柄的目的。这是一个现有代码,因此我保持原样。在父进程和子进程中,我将变量$ g_LOGFILE设置为包含不同的文件名,以便创建单独的日志文件。我也在父进程和子进程中都调用setEnvironment函数。我尝试通过在子进程中关闭STDOUT,STDERR,STDIN并调用setenvironment,但无法正常工作。

sub setEnvironment()
{   

  unless ( open(OUT, ">&STDOUT") )
   {
          print "Cannot redirect STDOUT";
          return 2;
    }
    unless ( open(ERR, ">&STDERR") )
    {
          print "Cannot redirect STDERR";
          return 2;
    }


  unless ( open(STDOUT, "|tee -ai $g_LOGPATH/$g_LOGFILE") )
  {
          print "Cannot open log file $g_LOGPATH/$g_LOGFILE");
          return 2;
   }
   unless ( open(STDERR, ">&STDOUT") )
   {
                print  "Cannot redirect STDERR");
                return 2 ;
    }
    STDOUT->autoflush(1);

} 


####################### Main Program ######################################

    $g_LOGFILE="parent.log";

  while ($file = readdir(DIR))
 {  
     my $pid = fork;
     if ( $pid ) {

        setEnvironment();
        #parent process code goes here
        printf "%s\n", "parent";
        next;
     }
     $g_LOGFILE="child.log";
     setEnvironment();
     #child code goes here
     printf "%s\n", "child";
     exit;
 }

wait for @pids
Run Code Online (Sandbox Code Playgroud)

PSI*_*Alt 3

好吧,我测试了这段代码。这是我的示例代码。在我的代码中存在类似(不完全)的问题:所有消息都双重写入子日志文件。

所以我对你的问题的回答:

问题是子进程 STDOUT 被重定向到父日志文件以及子日志文件。

这是因为当您使用管道(open(STDOUT, "|tee ...)作为基础结果打开文件时,您的进程fork()将创建子进程,然后exec进入您运行的程序(tee)。Forking(对于 tee)采用主进程的 STDOUT,因此tee将写入父进程的日志文件。所以我认为你必须撤销对主进程使用 STDOUT 句柄。或者,第二种方法 - 删除使用tee- 这是最简单的方法。

我也不明白下面的 setEnvironment 函数中创建 OUT 和 ERR 文件句柄的目的。

似乎这是有人对上述问题的担忧。您可以grep -rE ' \bERR\b' .在代码中搜索是否使用过。可能有人想保存真实的 STDOUT 和 STDERR 以供进一步使用。