2011-12-09 5 views
6

회귀 테스트를위한 일련의 배치 스크립트를 실행하는 perl 스크립트가 있습니다. 배치 스크립트에 타임 아웃을 구현하고 싶습니다. 현재 다음 코드가 있습니다.서브 프로세스가있는 perl 알람

my $pid = open CMD, "$cmd 2>&1 |"; 
    eval { 
       # setup the alarm 
       local $SIG{ALRM} = sub { die "alarm\n" }; 
       # alarm on the timeout 
       alarm $MAX_TIMEOUT; 
       log_output("setting alarm to $MAX_TIMEOUT\n"); 

       # run our exe 
       while(<CMD>) { 
         $$out_ref .= $_; 
       } 
       $timeRemaining = alarm 0; 
      }; 
      if ([email protected]) { 
        #catch the alarm, kill the executable 
      } 

문제는 내가 최대 제한 시간을 설정 했더라도 알람이 절대로 작동하지 않는다는 것입니다. Perl :: Unsafe :: Signals를 사용해 보았지만 도움이되지 않았습니다.

출력을 캡처 할 수있게하려면 배치 스크립트를 실행하는 가장 좋은 방법입니까? 알람을 사용할 수있는 동일한 작업을 수행하는 또 다른 방법이 있습니까, 아니면 프로그램을 제한 시간 초과하는 알람 외에 다른 방법이 있습니까?

알람이 내 perl 및 windows 버전에서 작동하는지 확인하기위한 테스트 스크립트를 만들었지 만 이와 같은 명령을 실행하면 작동하지 않습니다.

Windows 7 x64에서 activeperl 5.10.1을 실행 중입니다.

답변

4

alarm가 작동 할 때 시스템 호출과 같은 코드 등, 서로 다른 운영 체제에서 다르게

를 작동 할 수 있습니다 방법 SIGALRM,에 의해 중단되지 않습니다 때, 말할 어려운 작업 시간의 경우 당신이 시작한 서브 프로세스를 죽이려고합니다. 별도의 프로세스에서

my $pid = open CMD, "$cmd 2>&1 |"; 
my $time = $MAX_TIMEOUT; 

my $poor_mans_alarm = "sleep 1,kill(0,$pid)||exit for 1..$time;kill -9,$pid"; 
if (fork() == 0) { 
    exec($^X, "-e", $poor_mans_alarm); 
    die "Poor man's alarm failed to start"; # shouldn't get here 
} 
# on Windows, instead of fork+exec, you can say 
# system 1, qq[$^X -e "$poor_mans_alarm"] 


... 

가난한 사람의 알람 실행 :이 가난한 사람의 경보에 대한 좋은 사용 사례입니다. 매 초마다 식별자가 $pid 인 프로세스가 아직 살아 있는지 확인합니다. 프로세스가 살아 있지 않으면 경보 프로세스가 종료됩니다. 만약 프로세스가 여전히 $time 초 후에 살아 있다면 프로세스에 kill 시그널을 보낸다. (나는 9를 사용하여 untrappable이되고 -9는 전체 서브 프로세스 트리를 제거하기 위해 필요에 따라 다를 수있다.)

(실제로는 exec이 필요하지 않을 수 있습니다.이 관용구를 사용하여 Perl 스크립트보다 오래 지속되는 프로세스를 모니터링하기 때문에이 메서드를 사용합니다.이 문제는이 경우가 아니므로 건너 뛸 수 있습니다. exec 호출하고 대신

if (fork() == 0) { 
    for (1..$time) { sleep 1; kill(0,$pid) || exit } 
    kill -9, $pid; 
    exit; 
} 

을 말한다.)

관련 문제