2010-03-18 5 views
2

저는 Perl 초보자이며 "시스템"호출을 사용하는 데 약간의 문제가 있습니다.왜 Perl 시스템 호출이 점으로 실패합니까?

# First command is : 
# dot -Tpng $dottmpfile > $pngfile 
# Second command is : 
# rm $dottmpfile 

if (!($pngfile eq "")) { 
    my @args = ("dot", "-Tpng", $dottmpfile, " > ", $pngfile); 
    system (join (' ' , @args)) 
    or die "system @args failed : $!"; 

    unlink $dottmpfile; 
} 

편집 : 저는 여기에 2 개 쉘 명령을 실행하려고 코드의 작은 조각 여기 내 코드는 지금, 그리고 난 여전히 오류 얻을 : 나는 system을 사용했습니다

system dot -Tpng toto.dot > toto.png failed : Inappropriate ioctl for device at /home/claferri/bin/fractal.pl line 79. 

을 이 코드를 생성합니다.

+2

을 빨리, 전체 줄을 하나의 문자열로 병합하고 주위에 역 따옴표를 넣으십시오. 즉 $ result = \'dot -Tpng $ dottmpfile> $ pngfile \'; –

+1

여기를 참조하십시오 : http://stackoverflow.com/questions/2461472/how-can-i-run-an-external-command-and-capture-its-output-in-perl/2461664#2461664. 또한 파일을 지우려면'unlink()'를 사용하십시오.'rm '시스템을 호출 할 필요가 없음 – ghostdog74

+2

$! $보다는 오히려? - 오류 코드가 아닌 오류 메시지를 제공하며, 이는 거의 항상 잘못된 정보를 알려줍니다. –

답변

3

참고 perldoc -f system 찾고는리스트가 하나 개 이상의 값을 갖는 배열 인 경우 LIST 하나 이상의 인자가 있으면

하거나,리스트의 첫번째 요소에 의해 지정된 프로그램을 시작 인수는 나머지 목록에서 제공됩니다. 하나의 스칼라 인수가 있으면, 인수는 쉘 메타 문자를 검사하고, 어떤이있는 경우, 전체 인수는 그래서 >이 될 수있을 테니까요 당신은 system LIST를 호출하는

를 구문 분석 시스템의 명령 쉘에 전달 쉘에 의해 해석되는 대신 dot으로 전달되었습니다.

system LIST을 계속 사용하는 것이 좋습니다. 쉘을 통해 모든 것을 전달하는 것보다 조금 안전하기 때문입니다. 문서에 따르면 dot-o 옵션을 사용하여 출력 파일을 지정할 수 있으므로 그렇게하십시오.

당신이 정말로 당신의 내가의를 점하고 들 (말장난하지 않음) 교차하고 싶은 경우에, 당신은 사용할 수 있습니다 : 성공 0이 아닌 값에

if (defined $pngfile and $pngfile ne '') { 
    my @args = (dot => '-Tpng', $dottmpfile, "-o$pngfile"); 
    if (system @args) { 
     warn "'system @args' failed\n"; 
     my $reason = $?; 
     if ($reason == -1) { 
      die "Failed to execute: $!"; 
     } 
     elsif ($reason & 0x7f) { 
      die sprintf(
       'child died with signal %d, %s coredump', 
       ($reason & 0x7f), 
       ($reason & 0x80) ? 'with' : 'without' 
      ); 
     } 
     else { 
      die sprintf('child exited with value %d', $reason >> 8); 
     } 
    } 
    warn "'system @args' executed successfully\n"; 
    unlink $dottmpfile; 
} 
+0

나에게 당신이 추천하는 것을 얻지 못합니까? 아니면 "하지 않을"것을 말하고 싶습니까? 그럼 내가 뭘 써야 할까? 필자가 필요로하는 것은 dot 명령을 처리하고 $ pngfile에서 결과를 얻는 것입니다 ('>'를 사용하면 첫 번째 반사광이었습니다. 왜냐하면 필자가 bash에서하는 방식이기 때문에, 필자가 생각하기에 더 나은 방법이있을 수 있습니다.)) – claf

+1

@claferri 쉘 리다이렉션 연산자'>'보다는'-o' 옵션을 사용하여'시스템리스트 '형식을 유지하고 출력 파일을 지정하도록 권장합니다. –

+0

그게 훨씬 더 분명해 보인다 :) thx! – claf

3

system LIST을 사용하여 출력을 파일로 리디렉션하도록 셸에 알리기 위해 >을 사용 중이라면 셸을 우회합니다. 따라서, 당신은 사용할 수 있습니다

system (join (' ' , @args)); 

또는

system "@args"; 
+0

@pavun 목록을 단일 문자열과 '시스템'(또는'qx')에 전달하는 것과 결정적인 차이가 있습니다. –

+0

그리고 그것이 목록이고 문자열이 아니라는 사실은 claferri의 코드가 쉘 기능에 의존하기 때문에 작동하지 못하게하는 것입니다. – hobbs

+0

@hobbs : 그래서 내가 무슨 말을하는지 이해한다면, 문제는 목록에 공백이 없으며 조인 함수가 목록에서 공백으로 구분 된 요소가있는 문자열을 만드는 것입니다. – claf

-1

PATH에서 "점"실행인가? 실행 권한이 있습니까? 이 코드로 어떤 특정 오류가 발생합니까?

perldoc -f system에 따르면 정확하다고합니다.

+0

물론, dot은 잘 알려진 데비안 패키지이므로 문제의 원인이 될 수는 없습니다. – claf

+0

ummmmmm ... 나는 그것에 대해 들어 본 적이 없다.^_ ^> ... 정보를 주셔서 감사합니다. – darkturo

+0

텍스트 파일에서 그래프 이미지 (예 : png 파일)를 만드는 데 사용하는 그래프 도구 (패키지 : graphviz) 그래프, 매우 유용합니다;) – claf

1

system 0을 반환에 "실패". 이들 숙어의 대부분이 보는 방식과 약간의 직관에 반하는하지만 system 호출하면 같은 표현식 사용한다 : 당신은 그냥 가야하려면

system($command) and warn "system $command: failed $?\n"; # and not or 

또는

if (system($command) != 0) { ... handle error ... } 
관련 문제