2014-09-25 4 views
3

나는 CLI를 사용하여 Ruby 래퍼를 만들고있다. 그리고 난 Open3.capture3 (내부적으로는 Open3.popen3을 사용한다.) 명령을 실행하고 stdout, stderr 및 exit 코드를 캡처 할 수있는 깔끔한 방법을 발견했다.실행 파일이 없으면 Open3.popen3이 잘못된 오류를 반환하는 이유는 무엇입니까?

내가 탐지하고자하는 한 가지는 CLI 실행 파일을 찾을 수없는 경우 (그리고 그에 대한 특수 오류가 발생하는 경우)입니다. UNIX 쉘이 명령을 찾을 수 없을 때 종료 코드 127을 제공한다는 것을 알고 있습니다. 그리고 bash에서 $ foo을 실행하면 정확히 표시 할 오류 메시지 인 -bash: foo: command not found이 나옵니다. 내가 command = "foo" 그것을 실행했을 때, 나는 오류 얻을

require "open3" 

stdout, stderr, status = Open3.capture3(command) 
case status.exitstatus 
when 0 
    return stdout 
when 1, 127 
    raise MyError, stderr 
end 

:하지만

Errno::ENOENT: No such file or directory - foo 
    /Users/janko/.rbenv/versions/2.1.3/lib/ruby/2.1.0/open3.rb:193:in `spawn' 
    /Users/janko/.rbenv/versions/2.1.3/lib/ruby/2.1.0/open3.rb:193:in `popen_run' 
    /Users/janko/.rbenv/versions/2.1.3/lib/ruby/2.1.0/open3.rb:93:in `popen3' 
    /Users/janko/.rbenv/versions/2.1.3/lib/ruby/2.1.0/open3.rb:252:in `capture3' 

왜 이런 오류가 발생을 염두에두고 모든 것을 가진

, 나는 이런 식으로 코드를 작성? 난 Open3.capture3 그 쉘에서 직접 명령을 실행하기로되어 있다고 생각했는데, 왜 내가 정상적인 STDERR을 얻지 못하고 127의 종료 코드를 얻지 못했을까요?

답변

8

Open3.popen3 명령이 전달되는 방식에 따라 Kernel.spawn에 대한 대리자는 셸 또는 직접 OS에 명령을 제공합니다.

commandline     : command line string which is passed to the standard shell 
cmdname, arg1, ...   : command name and one or more arguments (This form does not use the shell. See below for caveats.) 
[cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell) 

우리는 우리가 Kernel.spawn("foo")를 호출하는 경우, 그것은 (OS가 아닌) 쉘에 전달 될 것이라고 기대하고 있습니다.

If the string from the first form (exec("command")) follows these simple rules: 

* no meta characters 
* no shell reserved word and no special built-in 
* Ruby invokes the command directly without shell 

You can force shell invocation by adding ";" to the string (because ";" is a meta character). 

마지막 단락은 솔루션을 보여준다 :하지만하지 않습니다, Kernel.exec에 대한 문서는 이유를 설명합니다.

require "open3" 

stdout, stderr, status = Open3.capture3(command + ";") 
case status.exitstatus 
when 0 
    return stdout 
when 1, 127 
    raise MyError, stderr 
end 
+0

유효하지만 유효합니다. 추가 할 매개 변수를 추가하려면 명령에 추가하십시오. 'Open3.capture3 ('ld --version'+ ';')'이렇게하면된다. Open3.capture3 ('ld', '--version'+ ';')' 이는 매개 변수를 추가하는 데 권장되는 방법입니다. – tukan

관련 문제