Linux 修改子进程的输出以添加时间戳

Linux 修改子进程的输出以添加时间戳,linux,perl,unix,fork,pipe,Linux,Perl,Unix,Fork,Pipe,我有一个用于分支子进程的perl脚本 sub my_exec{ my($args,$stdout, $stderr) = @_; my $processes = fork(); die("Cant fork") unless defined($processes); if(processes == 0){ if(defined $stdout){ close(STDOUT); open STDOUT,

我有一个用于分支子进程的perl脚本

sub my_exec{
    my($args,$stdout, $stderr) = @_;
    my $processes = fork();
    die("Cant fork") unless defined($processes);
    if(processes == 0){
        if(defined $stdout){
            close(STDOUT);
            open STDOUT, $stdout;
        }
        if(defined $stderr){
            close(STDERR);
            open STDERR, $stderr;
        }
        exec @$args;
    }else{
                ...
    }
}
我的主要问题是,我想为stderr的每一行输出添加一个时间戳。我想知道是否可以在这里做。正如您所看到的,stderr并不总是改变的。我想我可以通过某种管道来做?我还想重定向父脚本(同时将stdout和stderr重定向到文件的守护进程)以使用时间戳


谢谢

叉子
级别太低了。IPC::Open3是您应该使用的最小值

use IPC::Open3 qw( open3 );

open(local *CHILD_STDIN, '<', '/dev/null') or die $!;
open(local *CHILD_STDOUT, '>', $stdout) or die $!;

my $pid = open3(
   '<&CHILD_STDIN',
   '>&CHILD_STDOUT',
   \local *CHILD_STDERR,
   $prog, @$args
);

open(my $stderr_fh, '>', $stderr) or die $!;
while (<CHILD_STDERR>) {
   print $stderr_fh $ts . $_;
}

waitpid($pid, 0);
使用IPC::open3qw(Open3);
打开(本地*CHILD_STDIN,,$stdout)或死亡$!;
我的$pid=open3(
“&CHILD_STDOUT”,
\本地*CHILD_STDERR,
$prog,@$args
);
打开(我的$stderr_fh,'>',$stderr)或死亡$!;
而(){
打印$stderr\u fh$ts.$\uu;
}
waitpid($pid,0);

假设您编写了
my_exec
,如下所示

sub my_exec {
  my($args,$stdout,$stderr) = @_;  # caller untaints

  open my $oldout, ">&STDOUT" or die "$0: save STDOUT: $!";

  my $pid = open my $pipe, "-|" // die "$0: fork: $!";
  if ($pid) {
    if (defined $stderr) {
      open STDERR, ">", $stderr or die "$0: open: $!";
    }
    while (<$pipe>) {
      print STDERR scalar(localtime), ": ", $_;
    }
    close $pipe or die $! ? "$0: error closing $args->[0] pipe: $!"
                          : "$0: exit status " . ($? >> 8) . " from $args->[0]";
  }
  else {
    open STDERR, ">&STDOUT"    or die "$0: pipe STDERR: $!";
    if (defined $stdout) {
      open STDOUT, ">", $stdout or die "$0: open: $!";
    }
    else {
      open STDOUT, ">&", $oldout or die "$0: restore STDOUT: $!";
    }
    exec @$args or die "$0: exec @$args: $!";
  }
}
使用一个简单的

#! /usr/bin/env perl

print "Hello world!\n";
warn  "This is a warning.\n";
die   "All done.\n";
输出将转到不同的文件

1<代码>我的标准输出:

Hello world! Tue Nov 5 17:58:20 2013: This is a warning. Tue Nov 5 17:58:20 2013: All done. ./wrapper: exit status 255 from ./mydaemon at ./wrapper line 23.
open STDOUT,$STDOUT
打开一个输入文件句柄——这不是您想要的。嗯,$STDOUT在itIPC::Run中会有类似“>out.log”的内容,这可能是您想要的。我肯定在看IPC::Run。但是这可以用我目前运行东西的方式来完成吗(fork和exec)。@Smartelf是的,你可以用低级的方式来完成。请参见my.prob want
使用POSIX
然后
$ts=strftime(“%F%T”,localtime)或类似内容。人们通常希望在整个过程中使用相同的时间戳。谢谢。这是一个非常详细的答案。2个简短的问题。1) 此函数将等待孩子完成,对吗?(看起来是这样,只是要确保)2)等待不会影响perls信号处理(看起来也不错)。我不只是使用system命令的主要原因是,我需要在孩子运行时有一个响应信号处理程序。我只是想确保我没有遗漏任何东西。再次感谢。@Smartelf 1)while
循环读取
$pipe
上的所有输出,并假设当
读取行失败时,子对象已退出。如果您担心子进程将在退出之前关闭其标准错误,则可以在调用
close
之前添加额外的
waitpid
。2) 假设您使用的是PerlV5.8.0或更高版本,由于延迟信号,您应该处于良好状态。看见 Tue Nov 5 17:58:20 2013: This is a warning. Tue Nov 5 17:58:20 2013: All done. ./wrapper: exit status 255 from ./mydaemon at ./wrapper line 23.