[ruby] Ruby에서 쉘 명령을 호출하는 방법
Ruby 프로그램 내부에서 쉘 명령을 어떻게 호출합니까? 그런 다음이 명령의 출력을 Ruby로 다시 가져 오려면 어떻게합니까?
답변
이 설명은 주석을 기반으로합니다 내 친구의 루비 스크립트 를 . 스크립트를 개선하려면 링크에서 자유롭게 업데이트하십시오.
먼저 Ruby가 쉘을 호출 할 때 일반적으로 /bin/sh
, 하지 배쉬. 일부 /bin/sh
시스템에서 일부 Bash 구문이 지원되지는 않습니다 .
쉘 스크립트를 실행하는 방법은 다음과 같습니다.
cmd = "echo 'hi'" # Sample string that can be used
-
Kernel#`
일반적으로 백틱이라고합니다.`cmd`
이것은 Bash, PHP 및 Perl을 포함한 다른 많은 언어와 같습니다.
쉘 명령의 결과 (표준 출력)를 반환합니다.
문서 : http://ruby-doc.org/core/Kernel.html#method-i-60
value = `echo 'hi'` value = `#{cmd}`
-
내장 구문
%x( cmd )
x
문자 뒤에는 분리 문자가 있으며, 이는 임의의 문자 일 수 있습니다. 구분 기호는 문자 중 하나 인 경우(
,[
,{
, 또는<
, 문자 그대로 중첩 구분 쌍을 고려하여, 일치하는 닫는 구분 기호까지의 문자로 구성되어 있습니다. 다른 모든 구분 기호의 경우 리터럴은 다음에 나오는 구분 기호 문자까지의 문자로 구성됩니다. 문자열 보간#{ ... }
이 허용됩니다.백틱과 마찬가지로 쉘 명령의 결과 (예 : 표준 출력)를 반환합니다.
문서 : https://docs.ruby-lang.org/en/master/syntax/literals_rdoc.html#label-Percent+Strings
value = %x( echo 'hi' ) value = %x[ #{cmd} ]
-
Kernel#system
주어진 명령을 서브 쉘에서 실행합니다.
반환
true
명령, 발견하고 성공적으로 실행 된 경우false
.문서 : http://ruby-doc.org/core/Kernel.html#method-i-system
wasGood = system( "echo 'hi'" ) wasGood = system( cmd )
-
Kernel#exec
지정된 외부 명령을 실행하여 현재 프로세스를 대체합니다.
아무것도 반환하지 않으면 현재 프로세스가 교체되고 계속 진행되지 않습니다.
문서 : http://ruby-doc.org/core/Kernel.html#method-i-exec
exec( "echo 'hi'" ) exec( cmd ) # Note: this will never be reached because of the line above
다음은 몇 가지 추가 조언입니다
$?
같은 인 $CHILD_STATUS
, 당신은 역 따옴표를 사용하는 경우 마지막 시스템 실행 된 명령의 상태를 액세스, system()
또는 %x{}
. 그런 다음 exitstatus
및 pid
속성에 액세스 할 수 있습니다 .
$?.exitstatus
자세한 내용은 다음을 참조하십시오.
답변
다음은 ” Ruby에서 하위 프로세스를 시작하는 각 방법을 사용하는시기 “를 기반으로 한 순서도 입니다. 또한 ” 응용 프로그램이 stdout이 파이프가 아닌 터미널이라고 생각하도록 속임수 “를 참조하십시오 .
답변
내가 좋아하는 방법은 %x
리터럴을 사용하여 명령에서 따옴표를 사용하는 것이 쉽고 읽기 쉽습니다.
directorylist = %x[find . -name '*test.rb' | sort]
이 경우 현재 디렉토리 아래의 모든 테스트 파일로 파일 목록을 채우고 예상대로 처리 할 수 있습니다.
directorylist.each do |filename|
filename.chomp!
# work with file
end
답변
루비에서 쉘 스크립트를 실행하는 것에 대한 제 의견으로는 ” 루비에서 쉘 명령을 실행하는 6 가지 방법 “이 있습니다.
출력 만 가져 오려면 백틱을 사용하십시오.
STDOUT 및 STDERR과 같은 고급 기능이 필요했기 때문에 Open4 gem을 사용했습니다. 거기에 설명 된 모든 방법이 있습니다.
답변
내가 가장 좋아하는 것은 Open3
require "open3"
Open3.popen3('nroff -man') { |stdin, stdout, stderr| ... }
답변
이러한 메커니즘 중에서 선택할 때 고려해야 할 사항은 다음과 같습니다.
- 당신은 stdout을 원합니까 아니면 stderr도 필요합니까? 아니면 심지어 분리?
- 출력이 얼마나 큽니까? 전체 결과를 메모리에 저장 하시겠습니까?
- 서브 프로세스가 여전히 실행 중일 때 일부 출력을 읽으시겠습니까?
- 결과 코드가 필요하십니까?
- 프로세스를 나타내는 Ruby 객체가 필요하고 필요할 때 프로세스를 종료 할 수 있습니까?
당신은 (“), 간단한 역 따옴표에서 아무것도해야 할 수도 있습니다 system()
, 그리고 IO.popen
날려-전체에 Kernel.fork
/ Kernel.exec
로 IO.pipe
와 IO.select
.
하위 프로세스를 실행하는 데 시간이 너무 오래 걸리면 믹스에 타임 아웃을 던질 수도 있습니다.
불행히도, 그것은 매우 달려 있습니다.
답변
하나 더 옵션 :
때를:
- stdout뿐만 아니라 stderr 필요
- Open3 / Open4를 사용할 수 없습니다 / 사용할 수 없습니다 (내 Mac의 NetBeans에서 예외를 throw합니다. 이유는 모르겠습니다)
쉘 리디렉션을 사용할 수 있습니다.
puts %x[cat bogus.txt].inspect
=> ""
puts %x[cat bogus.txt 2>&1].inspect
=> "cat: bogus.txt: No such file or directory\n"