문제

다음은 시나리오입니다. 공통 라이브러리를 사용하는 많은 레거시 스크립트가 있습니다. 상기 스크립트는 진단 출력에 '인쇄'문을 사용합니다. 스크립트에 대한 변경 사항은 허용되지 않습니다. 멀리 떨어진 범위와 넓고 승인을 받았으며 오랫동안 유익한 감독과 통제의 계곡을 떠났습니다.

이제 새로운 요구가 도착했습니다. 이제 로깅이 라이브러리에 추가되어야합니다. 표준 라이브러리 사용자가 스크립트를 변경할 필요가 없으면 자동적이고 투명하게 수행해야합니다. 일반적인 라이브러리 방법은 단순히 로깅 통화가 추가 될 수 있습니다. 그것은 쉬운 부분입니다. 어려운 부분은이 스크립트의 진단 출력이 항상 '인쇄'문을 사용하여 표시되었다는 사실에 있습니다. 이 진단 출력은 저장되어야하지만 중요하게는 처리됩니다.

이 처리의 예로, 라이브러리는 '경고', '오류', '통지'또는 '주의'라는 단어가 포함 된 인쇄선 만 기록해야합니다. 아래의 매우 사소하고 고안된 예제 코드 (TM)는 상기 출력 중 일부를 기록합니다.

sub CheckPrintOutput
{
    my @output = @_; # args passed to print eventually find their way here.
    foreach my $value (@output) {
         Log->log($value) if $value =~ /warning|error|notice|attention/i;
    }
}

( '실제로 기록해야 할 것', '인쇄물을 진단에 사용해서는 안된다', 'Perl Sucks'또는 '이 예제 XY 및 Z'와 같은 문제를 피하고 싶습니다. 간결함과 명확성을 크게 단순화했습니다.)

기본적인 문제는 인쇄 (또는 그 추론 라인에 따라 모든 Perl 내장)를 전달한 데이터를 캡처하고 처리하는 데 따른다. 가능합니까? 깨끗하게 할 수있는 방법이 있습니까? 할 수있는 후크가있는 로깅 모듈이 있습니까? 아니면 전염병처럼 피해야 할 것인가, 인쇄 된 출력을 캡처하고 처리하는 것을 포기해야합니까?

추가 : Cross -Platform- Windows 및 *Nix 모두를 실행해야합니다. 스크립트를 실행하는 프로세스는 스크립트의 출력과 마찬가지로 동일하게 유지되어야합니다.

추가 추가 : CodeLogic의 답변에 대한 흥미로운 제안 :

서브 클래스를 할 수 있습니다 http://perldoc.perl.org/io/handle.html 로깅 작업을 수행 할 자신만의 파일 핸들을 만듭니다. - Kamil Kisiel

이것은 두 가지 경고와 함께 할 수 있습니다.

1)이 기능을 공통 라이브러리를 사용하는 사람 에게이 기능을 내보낼 수있는 방법이 필요합니다. Stdout과 아마도 stderr에 자동으로 적용해야합니다.

2) io :: 핸들 문서에 따르면 서브 클래스는 할 수 없으며 지금까지 내 시도는 결실이 없었습니다. Sublclassing io :: 핸들 작업을 만드는 데 필요한 특별한 것이 있습니까? 표준 '사용 기준'io :: handle '을 사용한 다음 새/인쇄 방법을 재정의하는 것은 아무것도하지 않는 것 같습니다.

최종 편집 : io :: 핸들이 막 다른 골목이지만 넥타이 :: 핸들이 할 수 있습니다. 모든 제안에 감사드립니다. 그들은 모두 정말 좋습니다. 나는 넥타이를 줄 것입니다 :: 경로를 다루겠습니다. 문제가 발생하면 돌아올 것입니다!

부록 :이 작업을 조금씩 작업 한 후에는 TIE :: 손잡이가 작동하는 것을 발견했습니다. 묶인 stdout 또는 stderr와 함께 io :: 핸들의 기능을 사용하는 경우 기본적으로 안정적으로 작동하는 것은 crapshoot입니다. IO :: 핸들의 자동 플러시 방법을 얻을 수있는 방법을 찾을 수 없었습니다. 핸들. 핸들을 묶기 전에 AutoFlush를 활성화하면 작동합니다. 그것이 당신에게 효과가 있다면, 넥타이 :: 핸들 경로가 허용 될 수 있습니다.

도움이 되었습니까?

해결책

재정의 할 수있는 많은 내장이 있습니다 ( Perlsub). 하지만, print 이런 식으로 작동하지 않는 내장 중 하나입니다. 우선의 어려움 print 이것에 대해 자세히 설명합니다 Perlmonk의 실.

그러나 당신은 ~할 수 있다

  1. 패키지를 만듭니다
  2. 손잡이를 묶습니다
  3. 이 핸들을 선택하십시오.

이제 두 사람이 기본 프레임 워크를 제공했지만 다음과 같이 작동합니다.

package IO::Override;
use base qw<Tie::Handle>;
use Symbol qw<geniosym>;

sub TIEHANDLE { return bless geniosym, __PACKAGE__ }

sub PRINT { 
    shift;
    # You can do pretty much anything you want here. 
    # And it's printing to what was STDOUT at the start.
    # 
    print $OLD_STDOUT join( '', 'NOTICE: ', @_ );
}

tie *PRINTOUT, 'IO::Override';
our $OLD_STDOUT = select( *PRINTOUT );

당신은 무시할 수 있습니다 printf 동일한 방법으로:

sub PRINTF { 
    shift;
    # You can do pretty much anything you want here. 
    # And it's printing to what was STDOUT at the start.
    # 
    my $format = shift;
    print $OLD_STDOUT join( '', 'NOTICE: ', sprintf( $format, @_ ));
}

보다 넥타이 :: 핸들 Stdout의 행동을 무시할 수있는 모든 것에 대해.

다른 팁

Perl을 사용할 수 있습니다 고르다 stdout을 리디렉션합니다.

open my $fh, ">log.txt";
print "test1\n";
my $current_fh = select $fh;
print "test2\n";
select $current_fh;
print "test3\n";

파일 핸들은 게시물이 로그 메시지를 처리하는 다른 프로세스의 파이프 일 수 있습니다.

Perlio :: 티 에서 Perlio :: Util 모듈을 사용하면 여러 대상 (예 : 로그 프로세서 및 STDOUT)에 대한 파일 핸들의 출력을 '티'할 수 있습니다.

많은 선택. select ()를 사용하여 인쇄 기본값을 변경하는 파일 핸들을 변경하십시오. 또는 넥타이 stdout. 또는 그것을 다시 열십시오. 또는 IO 레이어를 적용하십시오.

이것은 귀하의 문제에 대한 답이 아니지만 자신의 용도로 논리를 채택 할 수 있어야합니다. 그렇지 않다면 다른 사람이 유용하다고 생각할 것입니다.

기형 헤더를 잡기 전에 ...

package PsychicSTDOUT;
use strict;

my $c = 0;
my $malformed_header = 0;
open(TRUE_STDOUT, '>', '/dev/stdout');
tie *STDOUT, __PACKAGE__, (*STDOUT);

sub TIEHANDLE {
    my $class = shift;
    my $handles = [@_];
    bless $handles, $class;
    return $handles;
}

sub PRINT {
    my $class = shift;
    if (!$c++ && @_[0] !~ /^content-type/i) {
        my (undef, $file, $line) = caller;
        print STDERR "Missing content-type in $file at line $line!!\n";
        $malformed_header = 1;
    }
    return 0 if ($malformed_header);
    return print TRUE_STDOUT @_;
}
1;

용법:

use PsychicSTDOUT;
print "content-type: text/html\n\n"; #try commenting out this line
print "<html>\n";
print "</html>\n";

원본 스크립트의 stdout을 캡처하고 현명한 어딘가에 출력을 쓸 수있는 래퍼 스크립트에서 스크립트를 실행할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top