2012-09-26 5 views
6

Perl에서 한 프로그램에서 서브 루틴 내에서 호출 된 if 문에서 데이터를 평가합니다.Perl에는 현재 자체에서 실행중인 프로그램을 다시 시작하는 방법이 있습니까?

sub check_good { 
    if (!good) { 
     # exit this subroutine 
     # restart program 
    } 
    else { 
     # keep going 
    } 
} # end sub 

문제는 나가서 다시 시작하는 것입니다. 나는 밖으로 나가기 위해서 그냥 exit 0;을 사용할 수 있다는 것을 알고 있지만 처음으로 돌아가고 싶다면 분명히 올바르지 않습니다. 필자는 본질적으로 프로그램을 시작하는 서브 루틴 호출을 시도했지만, 일단 실행되면 다시이 시점으로 돌아갈 것입니다. while 루프에 넣는 방법에 대해 생각했지만이 방법은 전체 파일을 루프에 넣는 것을 의미 할 것이며 매우 비실용적입니다.

실제로 이것이 가능한지 여부는 알 수 없으므로 모든 입력 내용이 훌륭합니다.

답변

8

@ARGV을 변경하지 않았거나 사본을 보관하고 있다면 exec($^X, $0, @ARGV)과 같은 작업을 수행 할 수 있습니다.

$^X and $0 (또는 $EXECUTABLE_NAME$PROGRAM_NAME, 아래 브라이언의 의견을 참조)는 각각, 현재 펄 인터프리터와 현재의 펄 스크립트입니다.

+0

내 무지를 용서합니다. @ARGV가 명령 행 인수로 사용된다는 것을 알고 있지만, 을 사용할 수 있습니다. 나는 그들이 동일한 메모리 위치 (또는 무언가)에 데이터를 저장한다고 가정한다. – dgBP

+0

쉽게 테스트 할 수있는 주장입니다. – DavidO

+0

stdin을 소비하는 경우 임시 파일에서 직접 버퍼링해야합니다. – tripleee

-1

너 자신을 system라고 부르는 것을 막을 수있는 방법은 없습니다. 코드를 영원히 호출하지 못하도록 명령 줄 인수를 전달하는 이런 (명확한 정리가 필요한) 명확한 것.

#!/usr/bin/perl 
use strict; 
use warnings; 

print "Starting...\n"; 
sleep 5; 

if (! @ARGV) { 
     print "Start myself again...\n"; 
     system("./sleep.pl secondgo"); 
     print "...and die now\n"; 
     exit; 
} elsif ((@ARGV) && $ARGV[0] eq "secondgo") { 
     print "Just going to die straightaway this time\n"; 
     exit; 
} 
+0

이 해결 방법은 미리 고정 된 파일 이름에 따라 다릅니다. 다른 이름으로이 스크립트를 가리키는 여러 개의 링크 또는 심볼릭 링크가있을 때 그것은 빨기 시작합니다. 그리고 그것은 여전히'chdir'이 수행되지 않는다고 가정하고 있습니다 ... 또한 프로세스의 모든 단계를 생성하고 있습니다. 자신을 한 번 호출하는 것은 중요하지 않지만이 방법을 1000 번 다시 시작하면 프로세스 테이블과 RAM을 채우는 경향이 있습니다. – amon

+0

모든 요점에 동의하면, 나는 단지 자신을 다시 시작할 수 있음을 보여 주려고했습니다. 아래 답변과 명확하고 포괄적 인 답변. –

3

대안으로는 항상 감독자와 근로자의 두 가지 프로세스가 있어야합니다.

논리를 서브 루틴 run (또는 main 또는 무엇이든)으로 리팩터링하십시오. Whith 귀하의 실제 논리를 다시 시작해야합니다 그것은 예를 들어 1과 같은 미리 정의 된 비 - 제로 종료 코드 (종료)와 함께 종료해야합니다.

그런 다음 주 스크립트와 관리자가 다음과 같을 것이다 :

if (my $worker = fork) { 
    # child process 
    run(@ARGV); 
    exit 0; 
} 
# supervisor process 
waitpid $worker; 
my $status = ($? >> 8); 

if ($status == 1) { ... restart .. } 

exit $status; # propagate exit code... 

를 한 번만 다시 시작하려는 간단한 시나리오에서는이 조금 잔인한 수 있습니다. 그러나 다른 오류 시나리오를 처리 할 수 ​​있어야하는 경우이 방법이 더 좋을 수 있습니다.

예를 들어 종료 코드가 255이면 주 스크립트 인 die()가 있음을 나타냅니다. 이 경우 스크립트를 다시 시작하거나, 오류를 무시하거나, 문제를 에스컬레이션하기 위해 의사 결정 절차를 구현하는 것이 좋습니다.

CPAN에는 이러한 수퍼바이저를 구현하는 모듈이 많이 있습니다. Proc::Launcher은 그 중 하나이며 매뉴얼 페이지에는 관련 작업에 대한 광범위한 토론이 포함되어 있습니다. (필자는 Proc :: Launcher를 한번도 사용하지 않았습니다. 주로이 토론으로 인해 연결되었습니다.)

관련 문제