2009-03-11 18 views
10

मैं आउटपुट को आउटपुट से STDOUT और एक चर दोनों में भेजना चाहता हूं। मैं संयोजित करना चाहते हैं:मैं पर्ल आउटपुट दोनों को STDOUT और एक चर में कैसे भेज सकता हूं?

my $var = `some command` ; 
system('some command') ; 

Tee सही दिशा में एक कदम है, लेकिन यह है कि यह एक फ़ाइल के बजाय एक चर करने के लिए भेजता है। मुझे लगता है कि मैं तब फाइल पढ़ सकता था लेकिन इसे सीधे वहां लाने के लिए यह आसान होगा।

+0

मैंने टी की सीमाओं को दूर करने के लिए कैप्चर :: टिनी लिखा था। उदाहरण के लिए नीचे मेरा जवाब देखें। – xdg

उत्तर

9

आप Capture::Tiny

use Capture::Tiny 'tee'; 
my $output = tee { system("some command") }; 

चाहते मैं यह टी और लगभग 20 अन्य मॉड्यूल है कि कब्जा करने के कुछ प्रकार है, लेकिन एक ही रास्ता या किसी अन्य रूप में दोषपूर्ण हैं बदलने के लिए लिखा था।

- XDG (उर्फ dagolden)

+0

यह विंडोज़ पर मेरे लिए काम नहीं करता है, पर्ल एक सी ++ लॉन्चर लपेटता है जो सी # प्रोग्राम लॉन्च करता है। सभी लॉग आउटपुट कंसोल पर जाते हैं लेकिन मुझे एक ही आउटपुट फ़ाइल में नहीं मिल सकता है। किसी भी सलाह की सराहना की जाएगी हालांकि मैं सराहना करता हूं कि इस पर जाने के लिए बहुत कुछ नहीं है! – gav

+0

हाँ, यह विंडोज़ पर काम नहीं कर रहा है। क्या उनका कोई अन्य दृष्टिकोण है ?? – LearNer

15

क्या दोनों धाराओं के आउटपुट एक साथ हो सकते हैं?

यदि नहीं, तो आप कर सकता है:

my $var = 'cmd' 
my $output = `$cmd` 
print STDOUT $output 

या एक सुरक्षित संस्करण है, जो एक subshell लागू शामिल नहीं है, और प्रिंट एक समय में एक लाइन के लिए stdout के लिए:

sub backtick(@) 
{ 
    my $pid = open(KID, '-|'); 
    die "fork: $!" unless defined($pid); 
    if ($pid) { 
     my $output; 
     while (<KID>) { 
      print STDOUT $_; 
      $output .= $_; # could be improved... 
     } 
     close(KID); 
     return $output; 
    } else { 
     exec @_; 
    } 
} 

my @cmd = ('/bin/ls', '-l'); 
my $output = backtick(@cmd); 
+0

हां - मैं एचटीई आउटपुट को एसटीडीओयूटी को अनुकरण करने के लिए पसंद करूंगा - यह काफी लंबा हो सकता है और इससे उपयोगकर्ता को कुछ गर्म हो रहा है। – justintime

+0

ठीक है, नवीनतम संपादन यह करता है - यद्यपि लाइन-buffered। – Alnitak

+0

क्या आप 'my $ pid = open (KID, '- |') के बारे में और बात कर सकते हैं; 'और यह कैसे काम करता है? – gbtimmon

0

टी मॉड्यूल से आउटपुट को /dev/stdout (या /dev/fd/1) पर भेजें।

+0

यह मानता है कि लक्ष्य ओएस पर ऐसी चीज मौजूद है, और ऐसा कोई संकेत नहीं है कि यह करता है। –

+0

अच्छा, हाँ, यह धारणा करता है, और यदि ओ/एस इसका समर्थन नहीं करता है, तो नहीं, यह उत्तर लागू नहीं होता है। लेकिन जहां/dev/stdout सुविधा उपलब्ध है, यह टी को लागू करने के लिए तुच्छ बनाता है। –

1

आप एक स्ट्रिंग के लिए select() STDOUT करने के लिए IO::String मॉड्यूल का उपयोग और उसके बाद फोन system() आदेश को चलाने के लिए कर सकता है। आप IO::String हैंडल से आउटपुट एकत्र कर सकते हैं। बैकटिक सिंटैक्स क्या करता है यह प्रभावी ढंग से करता है।

तो आदेश उत्पादन वास्तविक समय इकट्ठा एसिंक्रोनस fork() या कुछ अन्य साधनों के माध्यम से system() आदेश चला और अपडेट के लिए संभाल सर्वेक्षण करना।

संपादित करें: प्रति ओपी, यह पता चला है कि यह दृष्टिकोण काम नहीं करता है। select()system() कॉल को प्रभावित नहीं करता है।

इसके अलावा, IO::String को open() सिंटैक्स के साथ बदल दिया गया है क्योंकि पर्ल 5.8 जो एक ही कार्य करता है।

+0

पर्ल 5.8 के बाद से आप एक चर को सीधे एक एफएच खोल सकते हैं, उदाहरण के लिए, खोलें (मेरा $ एफएच, ">" \ my $ वैरिएबल) या "एरर: $!" मरें। तो आईओ :: स्ट्रिंग (या आईओ :: स्केलर इत्यादि) के लिए और आवश्यकता नहीं है – runrig

+0

हर दिन कुछ नया सीखें ... – spoulson

+0

ऐसा लगता है कि चयन "सिस्टम" से आउटपुट को रीडायरेक्ट नहीं करता है जो दयालु है। – justintime

2

शायद मेरा उत्तर यहाँ आप मदद कर सकते हैं: How can I hook into Perl’s print?

+0

मैं नहीं देख सकता कि कैसे - यह पर्ल नहीं है जो आउटपुट कर रहा है, यह बाल प्रक्रिया है। – Alnitak

1

आप को संभालने के साथ ही एक फ़ाइल के माध्यम से ऐसा कर सकते हैं। कुछ समाधानों के रूप में सुरुचिपूर्ण नहीं है, लेकिन यह संभवतः काम करेगा। की तर्ज पर कुछ:

my $foo; 
open(READ, "env ps |"); 
while (<READ>) { 
    print; 
    $foo .= $_; 
} 
print $foo; 
close(READ); 
0
package Logger ; 
    # docs at the end ... 
    use lib '.' ; use strict ; use warnings ; use Carp qw(cluck); 

    our ($MyBareName , $LibDir , $RunDir) =() ; 

    BEGIN {  


     $RunDir = '' ; 
     $0 =~ m/^(.*)(\\|\/)(.*)\.([a-z]*)/; 
     $RunDir = $1 if defined $1 ; 
     push (@INC , $RunDir) ;  
     #debug print join (' ' , @INC) ; 

    } #eof sub 

    use Timer ; use FileHandler ; 

    # the hash holding the vars 
    our $confHolder =() ; 

    # =============================================================== 
    # START OO 


    # the constructor 
    sub new { 

     my $self = shift; 
     #get the has containing all the settings 
     $confHolder = ${ shift @_ } ;           
     # Set the defaults ... 
     Initialize() ;  
     return bless({}, $self); 
    } #eof new 


    BEGIN { 

      # strip the remote path and keep the bare name 
      $0=~m/^(.*)(\\|\/)(.*)\.([a-z]*)/; 
      my ($MyBareName , $RunDir) =() ; 
      $MyBareName = $3; 
      $RunDir= $1 ; 

      push (@INC,$RunDir) ; 

    } #eof BEGIN 


    sub AUTOLOAD { 

     my $self = shift ; 
     no strict 'refs'; 
      my $name = our $AUTOLOAD; 
      *$AUTOLOAD = sub { 
     my $msg = "BOOM! BOOM! BOOM! \n RunTime Error !!!\nUndefined Function $name(@_)\n" ; 
     print "$self , $msg"; 
      }; 
      goto &$AUTOLOAD; # Restart the new routine. 
    } 

    sub DESTROY { 

     my $self = shift; 
     #debug print "the DESTRUCTOR is called \n" ; 
     return ; 
    } 

    END { 

     close(STDOUT) || die "can't close STDOUT: $! \n\n" ; 
     close(STDERR) || die "can't close STDERR: $! \n\n" ; 
    } 

    # STOP OO 
    # ============================================================================= 

    sub Initialize { 

     $confHolder = { Foo => 'Bar' , } unless ($confHolder) ; 
     # if the log dir does not exist create it 
     my $LogDir = '' ; 
     $LogDir = $confHolder->{'LogDir'} ; 

     # create the log file in the current directory if it is not specified 
     unless (defined ($LogDir)) { 
     $LogDir = $RunDir ; 
     } 

    use File::Path qw(mkpath); 

     if(defined ($LogDir) && !-d "$LogDir") { 
       mkpath("$LogDir") || 
       cluck (" Cannot create the \$LogDir : $LogDir $! !!! " ) ; 
     } 

     # START set default value if value not specified ========================= 
     # Full debugging .... 
      $confHolder->{'LogLevel'} = 4 
        unless (defined ($confHolder->{'LogLevel'})) ; 

      $confHolder->{'PrintErrorMsgs'} = 1  
        unless (defined ($confHolder->{'PrintErrorMsgs'})) ; 

      $confHolder->{'PrintDebugMsgs'} = 1 
        unless (defined ($confHolder->{'PrintDebugMsgs'})) ; 

      $confHolder->{'PrintTraceMsgs'} = 1 
        unless (defined ($confHolder->{'PrintTraceMsgs'})) ; 

      $confHolder->{'PrintWarningMsgs'} = 1 
        unless (defined ($confHolder->{'PrintWarningMsgs'})) ; 

      $confHolder->{'LogMsgs'} = 1 
        unless (defined ($confHolder->{'LogMsgs'})) ; 

      $confHolder->{'LogTimeToTextSeparator'} = '---' 
        unless (defined ($confHolder->{'LogTimeToTextSeparator'})) ; 


     # 
     # STOP set default value if value not specified ========================= 

    } #eof sub Initialize 

    # ============================================================================= 
    # START functions 


    # logs an warning message 
    sub LogErrorMsg { 

     my $self = shift ; 
     my $msg = "@_" ; 
     my $msgType = "ERROR" ; 

     # Do not print anything if the PrintWarningMsgs = 0 
     return if ($confHolder->{'LogMsgs'} == 0)  ; 

     # Do not print anything if the PrintWarningMsgs = 0 
     return if ($confHolder->{'PrintErrorMsgs'} == 0) ; 

     $self->LogMsg($msgType , "$msg") if ($confHolder->{'PrintErrorMsgs'} == 1) ; 

    } #eof sub 

    # logs an warning message 
    sub LogWarningMsg { 

     my $self = shift ; 
     my $msg = "@_" ; 
     my $msgType = 'WARNING' ; 

     # Do not print anything if the PrintWarningMsgs = 0 
     return if ($confHolder->{'LogMsgs'} == 0)  ; 

     # Do not print anything if the PrintWarningMsgs = 0 
     return if ($confHolder->{'PrintWarningMsgs'} == 0) ; 

     $self->LogMsg($msgType , "$msg") if ($confHolder->{'PrintWarningMsgs'} == 1) ; 

    } #eof sub 



    # logs an info message 
    sub LogInfoMsg { 

     my $self = shift ; 
     my $msg = "@_" ; 
     my $msgType = 'INFO' ; 

     # Do not print anything if the PrintWarningMsgs = 0 
     return if ($confHolder->{'LogMsgs'} == 0)  ; 

     # Do not print anything if the PrintWarningMsgs = 0 
     return if ($confHolder->{'PrintInfoMsgs'} == 0) ; 

     $self->LogMsg($msgType , "$msg") if ($confHolder->{'PrintInfoMsgs'} == 1) ; 

    } #eof sub 

    # logs an trace message 
    sub LogTraceMsg { 

     my $self = shift ; 
     my $msg = "@_" ; 
     my $msgType = 'TRACE' ; 
     my ($package, $filename, $line) = caller();  


     # Do not print anything if the PrintDebugMsgs = 0 
     return if ($confHolder->{'PrintTraceMsgs'} == 0)  ; 

     $msg = "$msg : FROM Package: $package FileName: $filename Line: $line " ; 

     # Do not print anything if the PrintWarningMsgs = 0 
     return if ($confHolder->{'LogMsgs'} == 0)  ; 

     # Do not print anything if the PrintWarningMsgs = 0 
     return if ($confHolder->{'PrintTraceMsgs'} == 0) ; 

     $self->LogMsg($msgType , "$msg") if ($confHolder->{'PrintTraceMsgs'} == 1) ; 

    } #eof sub 

    # logs an Debug message 
    sub LogDebugMsg { 

     my $self = shift ; 
     my $msg = "@_" ; 
     my $msgType = 'DEBUG' ; 

     # Do not print anything if the PrintWarningMsgs = 0 
     return if ($confHolder->{'LogMsgs'} == 0)  ; 

     # Do not print anything if the PrintWarningMsgs = 0 
     return if ($confHolder->{'PrintDebugMsgs'} == 0) ; 

     $self->LogMsg($msgType , "$msg") if ($confHolder->{'PrintDebugMsgs'} == 1) ; 

    } #eof sub 

    sub GetLogFile { 

      my $self = shift ; 
      #debug print "The log file is " . $confHolder->{ 'LogFile' } ; 
      my $LogFile = $confHolder->{ 'LogFile' } ; 

      #if the log file is not defined we create one 
      unless ($confHolder->{ 'LogFile' }) { 

       $LogFile = "$0.log" ; 

      } 

      return $LogFile ; 
    } #eof sub 

    sub BuildMsg { 

    my $self = shift ; 
    my $msgType = shift ; 

    my $objTimer= new Timer(); 
    my $HumanReadableTime = $objTimer->GetHumanReadableTime(); 
    my $LogTimeToTextSeparator = $confHolder->{'LogTimeToTextSeparator'} ; 

    my $msg =() ; 

     # PRINT TO STDOUT if 
     if (    $msgType eq 'WARNING' 
        ||  $msgType eq 'INFO' 
        ||  $msgType eq 'DEBUG' 
        ||  $msgType eq 'TRACE'     ) { 

      $msg = " $HumanReadableTime $LogTimeToTextSeparator $msgType : @_ \n" ; 

     } 
     elsif ($msgType eq 'ERROR') { 

      $msg = " $HumanReadableTime $LogTimeToTextSeparator $msgType : @_ \n" ; 

     } 
     else { 
      $msg = " $HumanReadableTime $LogTimeToTextSeparator $msgType @_ \n" ; 
     } 



     return $msg ; 
    } #eof sub BuildMsg 

    sub LogMsg { 

    my $self = shift ; 
    my $msgType = shift ; 

    my $msg = $self->BuildMsg ($msgType , @_) ; 
    my $LogFile = $self -> GetLogFile();        


    # Do not print anything if the LogLevel = 0 
    return    if ($confHolder->{'LogLevel'} == 0) ; 

     # PRINT TO STDOUT if 
     if (    
           $confHolder->{'PrintMsgs'} == 1 
        ||  $confHolder->{'PrintInfoMsgs'} == 1 
        ||  $confHolder->{'PrintDebugMsgs'} == 1 
        ||  $confHolder->{'PrintTraceMsgs'} == 1 
        ) { 

      print STDOUT $msg ; 
     } 

     elsif ($confHolder->{'PrintErrorMsgs'} ) { 

      print STDERR $msg ; 
     } 


     if ($confHolder->{'LogToFile'} == 1) { 

      my $LogFile = $self -> GetLogFile(); 
      my $objFileHandler = new FileHandler(); 

      $objFileHandler->AppendToFile($LogFile , "$msg" ); 

     } #eof if 

     #TODO: ADD DB LOGGING 

    } #eof LogMsg 



    # STOP functions 
    # ============================================================================= 


    1; 

    __END__ 



    =head1 NAME 

    Logger 

    =head1 SYNOPSIS 

    use Logger ; 


    =head1 DESCRIPTION 

    Provide a simple interface for dynamic logging. This is part of the bigger Morphus tool : google code morphus 
    Prints the following type of output : 

    2011.06.11-13:33:11 --- this is a simple message 
    2011.06.11-13:33:11 --- ERROR : This is an error message 
    2011.06.11-13:33:11 --- WARNING : This is a warning message 
    2011.06.11-13:33:11 --- INFO : This is a info message 
    2011.06.11-13:33:11 --- DEBUG : This is a debug message 
    2011.06.11-13:33:11 --- TRACE : This is a trace message : FROM Package: Morphus 
    FileName: E:\Perl\sfw\morphus\morphus.0.5.0.dev.ysg\sfw\perl\morphus.pl Line: 52 

    =head2 EXPORT 


    =head1 SEE ALSO 

    perldoc perlvars 

    No mailing list for this module 


    =head1 AUTHOR 

    [email protected] 

    =head1 COPYRIGHT AND LICENSE 

    Copyright (C) 2011 Yordan Georgiev 

    This library is free software; you can redistribute it and/or modify 
    it under the same terms as Perl itself, either Perl version 5.8.1 or, 
    at your option, any later version of Perl 5 you may have available. 



    VersionHistory: 
    1.4.0 --- 2011.06.11 --- ysg --- Separated actions of building and printing msgs. Total refactoring. Beta . 
    1.3.0 --- 2011.06.09 --- ysg --- Added Initialize 
    1.2.0 --- 2011.06.07 --- ysg --- Added LogInfoErrorMsg print both to all possible 
    1.1.4 --- ysg --- added default values if conf values are not set 
    1.0.0 --- ysg --- Create basic methods 
    1.0.0 --- ysg --- Stolen shamelessly from several places of the Perl monks ... 

    =cut 
0

मेरी $ उत्पादन = प्रणाली ("अपने आदेश | टी/dev/tty");

मेरे लिए काम किया !!

संबंधित मुद्दे

 संबंधित मुद्दे