Menjalankan perintah baris perintah dalam skrip Ruby


92

Apakah ada cara untuk menjalankan perintah baris perintah melalui Ruby? Saya mencoba membuat program Ruby kecil yang akan memutar dan menerima / mengirim melalui program baris perintah seperti 'screen', 'rcsz', dll.

Akan sangat bagus jika saya bisa mengikat semua ini dengan Ruby (backend MySQL, dll.)


Kemungkinan duplikat dari perintah Calling shell dari Ruby
ymoreau

Jawaban:


209

Iya. Ada beberapa cara:


Sebuah. Gunakan %xatau '``:

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

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

Metode ini akan mengembalikan stdout, dan mengarahkan stderr ke program.


b. Penggunaan system:

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

Metode ini kembali truejika perintah berhasil. Ini mengarahkan semua output ke program.


c. Penggunaan 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.

Itu menggantikan proses saat ini dengan yang dibuat oleh perintah.


d. (ruby 1.9) gunakan spawn:

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

Metode ini tidak menunggu proses untuk keluar dan mengembalikan PID.


e. Penggunaan IO.popen:

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

Metode ini akan mengembalikan IOobjek yang merepresentasikan input / output proses baru. Saat ini juga satu-satunya cara yang saya tahu untuk memberikan masukan program.


f. Gunakan Open3(pada 1.9.2 dan yang lebih baru)

require 'open3'

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

Open3memiliki beberapa fungsi lain untuk mendapatkan akses eksplisit ke dua aliran keluaran. Ini mirip dengan popen, tetapi memberi Anda akses ke stderr.


Bonus trik: io = IO.popen 'cat > out.log', 'r+'; menulis output perintah ke "out.log"
Narfanator

1
Apa pro dan kontra untuk masing-masing. Bagaimana saya memutuskan mana yang akan digunakan? Bagaimana jika menggunakan FileUtils[ ruby-doc.org/stdlib-1.9.3/libdoc/fileutils/rdoc/FileUtils.html] ?
Ava

1
Saya menjalankan perintah SVN menggunakan exec. Saya tidak ingin keluaran dari exec muncul di konsol. Saya ingin mengalihkannya sehingga saya dapat menyimpannya sebagai variabel dan melakukan beberapa pemrosesan. Bagaimana saya melakukannya ?
stack1

2
status. berhasil? tidak lagi berfungsi untuk saya di ruby ​​2.4, itu berubah menjadi status.success? :)
DanielG

14

Ada beberapa cara untuk menjalankan perintah sistem di 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"

Tetapi jika Anda benar-benar perlu melakukan input dan output dengan perintah stdin / stdout, Anda mungkin ingin melihat IO::popenmetode, yang secara khusus menawarkan fasilitas itu.


popen berfungsi dengan baik jika aplikasi Anda hanya memiliki standar keluar. Jika Anda memerlukan lebih banyak interaksi atau ingin melakukan sesuatu yang berbeda dengan stdout, stdin, dan terutama stderr, Anda juga ingin melihat 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

Ya, ini tentu bisa dilakukan tetapi metode penerapannya berbeda-beda, bergantung pada apakah program "baris perintah" yang dimaksud beroperasi dalam mode "Layar penuh" atau baris perintah. Program yang ditulis untuk baris perintah cenderung membaca STDIN dan menulis ke STDOUT. Ini bisa dipanggil langsung di dalam Ruby menggunakan metode backticks standar dan / atau panggilan system / exec.

Jika program beroperasi dalam mode "Layar Penuh" seperti layar atau vi maka pendekatannya harus berbeda. Untuk program seperti ini, Anda harus mencari implementasi Ruby dari pustaka "ekspektasi". Ini akan memungkinkan Anda untuk membuat skrip apa yang Anda harapkan untuk dilihat di layar dan apa yang harus dikirim ketika Anda melihat string tertentu muncul di layar.

Ini tidak mungkin menjadi pendekatan terbaik dan Anda mungkin harus melihat apa yang ingin Anda capai dan menemukan perpustakaan / permata yang relevan untuk melakukannya daripada mencoba mengotomatiskan aplikasi layar penuh yang ada. Sebagai contoh, " Perlu bantuan dengan komunikasi port serial di Ruby " berkaitan dengan komunikasi Port Serial, pra-kursor untuk panggilan jika itu yang ingin Anda capai dengan menggunakan program spesifik yang Anda sebutkan.


Versi sederhana dari Expect tersedia di Ruby menggunakan modul Pty bawaannya.
Manusia Timah

0

Metode Paling Digunakan Menggunakan di Open3sini adalah versi kode saya yang diedit dari kode di atas dengan beberapa koreksi:

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.