문제

사용할 때 체계() Perl에서 전화를 걸면 쉘 args를 피해야합니까, 아니면 자동으로 수행됩니까?

인수는 사용자 입력이므로이를 악용 할 수 없는지 확인하고 싶습니다.

도움이 되었습니까?

해결책

사용하는 경우 system $cmd, @args 보다는 system "$cmd @args" (문자열이 아닌 배열), 쉘이 호출되지 않기 때문에 인수를 피할 필요가 없습니다 ( 체계). system {$cmd} $cmd, @args $ cmd가 metacharacters를 포함하고 @args가 비어 있더라도 쉘을 호출하지 않습니다 (이것은의 일부로 문서화되어 있습니다. exec). Args가 사용자 입력 (또는 다른 신뢰할 수없는 소스)에서 나오는 경우에도 여전히 이해하지 못할 것입니다. 보다 -T 에서 Perlrun 문서와 Perlsec 문서.

출력을 읽거나 명령에 입력을 보내야하는 경우 qx 그리고 readpipe 동등한 것이 없습니다. 대신 사용하십시오 open my $output, "-|", $cmd, @args 또는 open my $input, "|-", $cmd, @args 이것은 실제가 필요하기 때문에 휴대 가능하지는 않지만 fork 그것은 유닉스만을 의미합니다 ... 나는 생각합니다. 아마도 시뮬레이션 된 포크로 Windows에서 작동 할 수도 있습니다. 더 나은 옵션은 같은 것입니다 IPC :: 실행, 또한, 파이핑 명령의 경우 다른 명령에 대한 경우, 멀티 아그 형태의 시스템이나 4 개의 Arg 형태가 처리되지 않을 것입니다.

다른 팁

창문에서는 상황이 약간 나빠요. 기본적으로 모든 Win32 프로그램은 하나의 긴 명령 줄 문자열 (일반적으로 쉘)을받습니다. cmd.exe) 먼저 해석을 수행 할 수 있습니다 < 그리고 > 예를 들어 리디렉션이지만 그렇습니다 ~ 아니다 프로그램의 Word 경계에서 분할하십시오. 각 프로그램은 이것을 스스로 파싱해야합니다 (원하는 경우 - 일부 프로그램은 귀찮게하지 않습니다). C 및 C ++ 프로그램에서 컴파일러 도구 체인과 함께 제공되는 런타임 라이브러리가 제공하는 루틴은 일반적 으로이 구문 분석 단계를 수행합니다. main() 호출됩니다.

문제는 일반적으로 주어진 프로그램이 어떻게 명령 줄을 구문 분석 할 것인지 모르겠습니다.. 많은 프로그램이 MSVC ++의 일부 버전으로 편집되어 있으며 기발한 구문 분석 규칙이 여기에 설명되어 있습니다, 그러나 다른 많은 사람들은 다른 규칙을 사용하는 다른 컴파일러로 컴파일됩니다.

이것은 사실에 의해 복잡해집니다 cmd.exe 자체 기발한 구문 분석 규칙이 있습니다. 캐럿 (^)는 다음 문자를 인용하는 탈출 문자로 취급되며, 이중 인용문 안에있는 텍스트는 까다로운 기준 목록이 충족되면 인용 된 것으로 취급됩니다 (참조 cmd /? 전체적인 세부 사항은). 명령에 이상한 문자가 포함되어 있으면 매우 쉽습니다. cmd.exe텍스트의 일부 부분이 "인용"되어 있고 대상 프로그램과 동기화되지 않아야하는지에 대한 아이디어는 모든 지옥이 느슨해집니다.

따라서 Windows에서 논쟁을 피하기위한 가장 안전한 접근법은 다음과 같습니다.

  1. 당신이 호출하는 프로그램의 명령 줄 구문 분석 논리에 의해 예상되는 방식으로 주장을 피하십시오. (그렇지 않으면 그 논리가 무엇인지 알고 있습니다. 그렇지 않다면 몇 가지 예를 들어보십시오.)
  2. 탈출 한 논쟁에 공간에 참여하십시오.
  3. 접두사 모든 단일 비 알파늄 문자 결과 문자열의 ^.
  4. 리디렉션 또는 기타 쉘 속임수를 추가하십시오 (예 : 명령에 가입 &&).
  5. 명령을 실행하십시오 system() 또는 백틱.
 sub esc_chars {
  # will change, for example, a!!a to a\!\!a
     @_ =~ s/([;<>\*\|`&\$!#\(\)\[\]\{\}:'"])/\\$1/g;
     return @_;
  }

http://www.slac.stanford.edu/slac/www/resource/how-to-us-ouse/cgi-rexx/cgi-esc.html

시스템 "$ cmd @args"(문자열)를 사용하는 경우 쉘이 호출되므로 인수를 피해야합니다.

다행스럽게도 이중 인용 문자열의 경우 4 개의 문자만이 탈출이 필요합니다.

"    - double quote
$    - dollar
@    - at symbol
\    - backslash

귀하의 질문에 대한 답변은 매우 유용했습니다. 결국 나는 @runrig의 조언을 따르지만 Core Module Open3 () 명령을 사용하여 stderr와 stdout의 출력을 캡처 할 수있었습니다.

@RunRig의 솔루션과 함께 사용중인 Open3 ()의 샘플 코드는 관련 질문 및 답변을 참조하십시오.
Perl에서 시스템 명령을 호출합니다

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