Ruby 스크립트 내에서 명령 줄 명령 실행


92

Ruby를 통해 명령 줄 명령을 실행하는 방법이 있습니까? 'screen', 'rcsz'등과 같은 명령 줄 프로그램을 통해 전화를 걸어주고받는 작은 Ruby 프로그램을 만들려고합니다.

이 모든 것을 Ruby (MySQL 백엔드 등)와 연결하면 좋을 것입니다.


답변:


209

예. 여러 가지 방법이 있습니다.


ㅏ. 사용 %x또는 '' ':

%x(echo hi) #=> "hi\n"
%x(echo hi >&2) #=> "" (prints 'hi' to stderr)

`echo hi` #=> "hi\n"
`echo hi >&2` #=> "" (prints 'hi' to stderr)

이 메서드는 stdout을 반환하고 stderr을 프로그램으로 리디렉션합니다.


비. 사용 system:

system 'echo hi' #=> true (prints 'hi')
system 'echo hi >&2' #=> true (prints 'hi' to stderr)
system 'exit 1' #=> nil

이 메서드는 true명령이 성공한 경우 반환 됩니다. 모든 출력을 프로그램으로 리디렉션합니다.


씨. 사용 exec:

fork { exec 'sleep 60' } # you see a new process in top, "sleep", but no extra ruby process. 
exec 'echo hi' # prints 'hi'
# the code will never get here.

그러면 현재 프로세스가 명령에 의해 생성 된 프로세스로 바뀝니다.


디. (루비 1.9) 사용 spawn:

spawn 'sleep 1; echo one' #=> 430
spawn 'echo two' #=> 431
sleep 2
# This program will print "two\none".

이 메서드는 프로세스가 종료 될 때까지 기다리지 않고 PID를 반환합니다.


이자형. 사용 IO.popen:

io = IO.popen 'cat', 'r+'
$stdout = io
puts 'hi'
$stdout = IO.new 0
p io.read(1)
io.close
# prints '"h"'.

이 메서드는 IO새 프로세스의 입력 / 출력을 반영 하는 개체를 반환합니다 . 또한 현재 프로그램 입력을 제공하는 유일한 방법입니다.


에프. 사용 Open3(1.9.2 이상)

require 'open3'

stdout,stderr,status = Open3.capture3(some_command)
STDERR.puts stderr
if status.successful?
  puts stdout
else
  STDERR.puts "OH NO!"
end

Open3두 출력 스트림에 대한 명시 적 액세스를 얻기위한 몇 가지 다른 기능이 있습니다. popen과 비슷하지만 stderr에 액세스 할 수 있습니다.


보너스 트릭 : io = IO.popen 'cat > out.log', 'r+'; "out.log"에 명령의 출력을 기록
Narfanator

1
각각의 장단점은 무엇입니까? 어떤 것을 사용할지 어떻게 결정합니까? 어떻게 사용에 대한 FileUtils[ ruby-doc.org/stdlib-1.9.3/libdoc/fileutils/rdoc/FileUtils.html]를 ?
Ava

1
exec를 사용하여 SVN 명령을 실행하고 있습니다. exec의 출력이 콘솔에 표시되는 것을 원하지 않습니다. 변수로 저장하고 이에 대해 처리 할 수 ​​있도록 리디렉션하고 싶습니다. 어떻게하나요?
stack1 2015-07-13

2
status.successful? 루비 2.4에서 더 이상 작동하지 않고 status.success로 변경 되었습니까? :)
DanielG

14

Ruby에서 시스템 명령을 실행하는 몇 가지 방법이 있습니다.

irb(main):003:0> `date /t` # surround with backticks
=> "Thu 07/01/2010 \n"
irb(main):004:0> system("date /t") # system command (returns true/false)
Thu 07/01/2010
=> true
irb(main):005:0> %x{date /t} # %x{} wrapper
=> "Thu 07/01/2010 \n"

그러나 명령의 stdin / stdout을 사용하여 실제로 입력 및 출력을 수행해야하는 경우 IO::popen특히 해당 기능을 제공하는 메서드 를보고 싶을 것입니다 .


popen은 앱이 표준 출력 만 있으면 잘 작동합니다. 더 많은 상호 작용이 필요하거나 stdout, stdin, 특히 stderr로 다른 작업을 수행하려면 open3도 살펴볼 수 있습니다. ruby-doc.org/core/classes/Open3.html
Paul Rubel

7
 folder = "/"
 list_all_files = "ls -al #{folder}"
 output = `#{list_all_files}`
 puts output

2

예, 이것은 확실히 가능하지만 구현 방법은 해당 "명령 줄"프로그램이 "전체 화면"또는 명령 줄 모드에서 작동하는지 여부에 따라 다릅니다. 명령 줄용으로 작성된 프로그램은 STDIN을 읽고 STDOUT에 쓰는 경향이 있습니다. 표준 백틱 메서드 및 / 또는 시스템 / exec 호출을 사용하여 Ruby 내에서 직접 호출 할 수 있습니다.

프로그램이 screen 또는 vi와 같은 "전체 화면"모드에서 작동하는 경우 접근 방식이 달라야합니다. 이와 같은 프로그램의 경우 "expect"라이브러리의 Ruby 구현을 찾아야합니다. 이렇게하면 화면에 표시 될 것으로 예상되는 내용과 해당 특정 문자열이 화면에 나타날 때 보낼 내용을 스크립트로 작성할 수 있습니다.

이것은 최선의 접근 방법이 아닐 수 있으며, 기존 전체 화면 응용 프로그램을 자동화하는 것보다 달성하려는 작업을 살펴보고이를 수행 할 관련 라이브러리 / 보석을 찾아야 할 것입니다. 예를 들어 " Ruby의 직렬 포트 통신에 대한 도움이 필요합니다 " 는 직렬 포트 통신을 다룹니다. 이것은 당신이 언급 한 특정 프로그램을 사용하여 달성하려는 경우 전화 걸기의 선구자입니다.


내장 된 Pty 모듈을 사용하여 Ruby에서 간단한 Expect 버전을 사용할 수 있습니다 .
Tin Man

0

가장 많이 사용되는 방법은 Open3여기에서 사용하는 것입니다. 위 코드의 수정 된 버전입니다.

require 'open3'
puts"Enter the command for execution"
some_command=gets
stdout,stderr,status = Open3.capture3(some_command)
STDERR.puts stderr
if status.success?
  puts stdout
else
  STDERR.puts "ERRRR"
end
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.