Rubyスクリプト内でコマンドラインコマンドを実行する


92

Rubyを介してコマンドラインコマンドを実行する方法はありますか?「screen」、「rcsz」などのコマンドラインプログラムを介してダイヤルアウトおよび受信/送信する小さなRubyプログラムを作成しようとしています。

これらすべてをRuby(MySQLバックエンドなど)と関連付けることができればすばらしいと思います。


回答:


209

はい。いくつかの方法があります。


a。%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をプログラムにリダイレクトします。


b。使用system

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

このメソッドはtrue、コマンドが成功した場合に返されます。すべての出力をプログラムにリダイレクトします。


c。使用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.

これにより、現在のプロセスがコマンドによって作成されたプロセスに置き換えられます。


d。(ルビー1.9)使用spawn

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

このメソッドは、プロセスが終了するのを待たずにPIDを返します。


e。使用IO.popen

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

このメソッドはIO、新しいプロセスの入出力を表すオブジェクトを返します。これは、現在、プログラムに入力を与える唯一の方法でもあります。


f。使用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には、2つの出力ストリームに明示的にアクセスするための関数がいくつかあります。これは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 2013

1
execを使用してSVNコマンドを実行しています。execの出力をコンソールに表示したくありません。それを変数として格納し、これに対していくつかの処理を実行できるように、リダイレクトしたい どうすればいいのですか ?
stack1 2015

2
status.successful?ruby 2.4で動作しなくなったため、status.successに変更されましたか?:)
DanielG 2017

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に書き込む傾向があります。これらは、標準のバックティックメソッドやシステム/実行呼び出しを使用して、Ruby内で直接呼び出すことができます。

プログラムがscreenまたはviのような「フルスクリーン」モードで動作する場合、アプローチは異なる必要があります。このようなプログラムでは、「期待」ライブラリのRuby実装を探す必要があります。これにより、画面に表示されるはずの内容をスクリプトで記述したり、特定の文字列が画面に表示されたときに送信する内容を記述したりできます。

これが最善のアプローチであるとは考えにくいため、おそらく既存のフルスクリーンアプリケーションを自動化するのではなく、達成しようとしていることを確認し、それを行うための関連ライブラリ/ gemを見つける必要があります。例として、「Rubyでのシリアルポート通信の支援が必要」は、シリアルポート通信を扱います。シリアルポート通信は、あなたが言及した特定のプログラムを使用してそれを実現したい場合にダイヤルするための前駆体です。


Expectの単純なバージョンは、組み込みのPtyモジュールを使用してRubyで利用できます。
ティンマン

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.