gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:55:38 24 4
gpt4 key购买 nike

我有一个派生子进程的 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 都重定向到文件的守护进程)也使用时间戳。

谢谢

最佳答案

假设您编写 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: $!";
}
}

要点在documentation on open中有描述。 :

If you open a pipe on the command - (that is, specify either |- or -| with the one– or two–argument forms of open), an implicit fork is done, so open returns twice: in the parent process it returns the pid of the child process, and in the child process it returns (a defined) 0. Use defined($pid) or // to determine whether the open was successful.

隐式 fork 的要点是在父进程和子进程之间建立管道。

The filehandle behaves normally for the parent, but I/O to that filehandle is piped from the STDOUT of the child process. In the child process, the filehandle isn’t opened—I/O happens from the new STDOUT.

这几乎是完美的,除了你想修改标准错误,而不是标准输出。

这意味着我们需要保存父级的 STDOUT 以便子级可以恢复它。这就是 $oldout 的情况。

将子进程的(重定向的)STDOUT 复制到它的 STDERR 安排底层守护进程的标准错误通过父进程读取、修改和输出的管道运行。

一个稍微棘手的点是处理重定向的地方。如果调用者想要重定向 STDOUT,则需要在子进程中进行。但是要重定向 STDERR,父级需要这样做,因为这使父级有机会修改流。

完整示例的代码具有以下形式。你提到了一个守护进程,所以我启用了 Perl’s dataflow analysis known as taint mode .

#! /usr/bin/perl -T

use strict;
use warnings;

use v5.10.0; # for defined-or //

$ENV{PATH} = "/bin:/usr/bin";

sub my_exec {
# paste code above
}

#my_exec ["./mydaemon"];
#my_exec ["./mydaemon"], "my-stdout";
my_exec ["./mydaemon"], "my-stdout", "my-stderr";

用一个简单的mydaemon

#! /usr/bin/env perl

print "Hello world!\n";
warn "This is a warning.\n";
die "All done.\n";

输出到单独的文件。

<强>1。 我的标准输出:

Hello world!

<强>2。 我的标准错误:

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.

关于linux - 修改子进程的输出以添加时间戳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19796583/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com