2010-07-19 4 views
3

En Perl, après fork() ing je peux rediriger la sortie standard d'un enfant dans un fichier comme siPerl, redirect stdout mais gardez le parent

open STDOUT,">",$filename or die $! 

Je me demande s'il y a un moyen de « copier », en gardant stdout sur la sortie stdout du parent mais aussi en le copiant dans un fichier spécifié. Cela devrait se faire d'une manière qui ne nécessiterait aucune mise en mémoire tampon et l'utilisateur verrait la sortie de la console en temps réel. Cela serait en quelque sorte comme l'unix tee. Mais idéalement, la solution n'impliquerait pas de bibliothèques tierces.

+7

Vous avez mentionné "idéalement" que la solution n'impliquerait pas de bibliothèques tierces, mais pour la postérité, IO :: Tee a été écrit pour résoudre ce problème et le fait très bien. – cikkle

+0

Je suppose qu'il devrait y avoir une façon simple de le faire en utilisant la construction dans le fichier io – Mike

Répondre

3

Chez l'enfant, exécutez

open STDOUT, "|-", "tee", $output 
    or die "$0: failed to start tee: $!"; 

Si vous ne souhaitez pas utiliser tee pour une raison quelconque, vous pouvez utiliser la version d'un pauvre homme par bifurquer un autre enfant par open STDOUT, "|-" et de faire la duplication dans la petit-enfant:

#! /usr/bin/perl 

use warnings; 
use strict; 

my $pid = fork; 
die "$0: fork: $!" unless defined $pid; 

if ($pid) { 
    waitpid $pid, 0; 
} 
else { 
    my $pid = open STDOUT, "|-"; 
    die "$0: fork: $!" unless defined $pid; 
    select STDOUT; $| = 1; # disable STDOUT buffering 
    if ($pid) { 
    print "Hiya!\n"; 
    system "echo Howdy"; 
    close STDOUT or warn "$0: close: $!"; 
    exit 0; 
    } 
    else { 
    open my $fh, ">", "/tmp/other-output" or die "$0: open: $!"; 
    my $status; 
    while ($status = sysread STDIN, my $data, 8192) { 
     syswrite $fh, $data and print $data or die "$0: output failed: $!"; 
    } 
    die "$0: sysread: $!" unless defined $status; 
    close $fh or warn "$0: close: $!"; 
    exit 0; 
    } 
} 

course de l'échantillon:

$ ./owntee 
Hiya! 
Howdy 

$ cat other-output 
Hiya! 
Howdy
0

Si le parent peut attendre pour l'enfant à finir, l'enfant pourrait conduit sa sortie au parent qui assume la responsabilité de l'impression à la fois STDOUT et le fichier de destination:

open my $destfile, '>', $path or die "Can't open destination file: $!\n"; 

my $pid = open my $child, '-|'; 
defined $pid or die "Can't fork: $!\n"; 

if ($pid == 0) { 
    # Child process: 
    print "I'm the child!\n"; 
    close $destfile; 
    # do whatever 
    exit; 
} 

# Parent process: 

while (<$child>) { 
    print STDOUT $_; 
    print $destfile $_; 
} 

close $child; 
close $destfile; 

En fait, même Si le parent ne peut pas attendre la fin de l'enfant, cette stratégie fonctionnera si le parent a d'abord forké un enfant pour exécuter la logique décrite ci-dessus.

Questions connexes