2010-07-01 47 views
76

Có cách nào để chạy các lệnh dòng lệnh thông qua Ruby không? Tôi đang cố tạo một chương trình Ruby nhỏ nhỏ có thể quay số và nhận/gửi qua các chương trình dòng lệnh như 'màn hình', 'rcsz', v.v.Chạy các lệnh dòng lệnh trong Ruby script

Sẽ tuyệt vời nếu tôi có thể kết hợp tất cả điều này với Ruby (MySQL backend, vv)

Trả lời

13

Có một vài cách để chạy các lệnh hệ thống trong 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" 

Nhưng nếu bạn cần phải thực sự thực hiện đầu vào và đầu ra với của lệnh stdin/stdout, có thể bạn sẽ muốn xem xét phương pháp IO::popen, mà cụ thể là cung cấp cơ sở đó.

+0

popen hoạt động tốt nếu ứng dụng của bạn chỉ có chuẩn ra. Nếu bạn cần tương tác nhiều hơn hoặc muốn làm điều gì đó khác với stdout, stdin và đặc biệt là stderr bạn cũng sẽ muốn xem xét trong open3: http://ruby-doc.org/core/classes/Open3.html –

180

Có. Có một số cách:


a. Sử dụng %x hoặc '`':

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

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

Những phương pháp này sẽ trả lại stdout, stderr và chuyển hướng tới các chương trình.


b. Sử dụng system:

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

Phương pháp này trả về true nếu lệnh đã thành công. Nó chuyển hướng tất cả đầu ra của chương trình.


c. Sử dụng 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. 

Đó thay thế quá trình hiện với một tạo ra bởi lệnh.


d. (ruby 1.9) sử dụng spawn:

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

Phương pháp này không chờ đợi cho quá trình để thoát ra và trả về PID.


e. Sử dụng IO.popen:

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

Phương pháp này sẽ trả về một đối tượng IO rằng reperesents các quá trình mới đầu vào/đầu ra. Nó cũng là cách duy nhất tôi biết để cung cấp cho đầu vào chương trình.


f. Sử dụng Open3 (trên 1.9.2 và sau này)

require 'open3' 

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

Open3 có một số chức năng khác để truy cập rõ ràng vào hai luồng đầu ra. Nó tương tự như popen, nhưng cho phép bạn truy cập vào stderr.

+0

Tóm tắt rực rỡ Adrian , cảm ơn bạn đã chia sẻ thông tin này. – KomodoDave

+0

Tiền thưởng: 'io = IO.popen 'cat> out.log', 'r +''; viết kết quả đầu ra của lệnh tới "out.log" – Narfanator

+1

Ưu điểm và nhược điểm của mỗi lệnh là gì. Làm cách nào để quyết định sử dụng? Làm thế nào về việc sử dụng 'FileUtils' [http://ruby-doc.org/stdlib-1.9.3/libdoc/fileutils/rdoc/FileUtils.html]? – Ava

2

Có điều này chắc chắn có thể thực hiện được nhưng phương pháp triển khai khác nhau phụ thuộc vào việc chương trình "dòng lệnh" đang hoạt động trong chế độ "Toàn màn hình" hay dòng lệnh. Các chương trình được viết cho dòng lệnh có xu hướng đọc STDIN và ghi vào STDOUT. Chúng có thể được gọi trực tiếp trong Ruby bằng cách sử dụng các phương thức backticks tiêu chuẩn và/hoặc các cuộc gọi hệ thống/exec.

Nếu chương trình hoạt động ở chế độ "Toàn màn hình" như màn hình hoặc vi thì cách tiếp cận phải khác nhau. Đối với các chương trình như thế này, bạn nên tìm kiếm một triển khai Ruby của thư viện "mong đợi". Điều này sẽ cho phép bạn để kịch bản những gì bạn mong đợi để xem trên màn hình và những gì để gửi khi bạn nhìn thấy những chuỗi cụ thể xuất hiện trên màn hình.

Đây không phải là cách tiếp cận tốt nhất và bạn nên xem xét những gì bạn đang cố gắng đạt được và tìm thư viện/đá quý có liên quan để thực hiện điều đó thay vì cố gắng tự động hóa ứng dụng toàn màn hình hiện có. Ví dụ: "Need assistance with serial port communications in Ruby" xử lý các giao tiếp Cổng nối tiếp, một con trỏ trước để quay số nếu đó là những gì bạn muốn đạt được bằng cách sử dụng các chương trình cụ thể mà bạn đã đề cập.

+0

Một phiên bản đơn giản của Mong đợi có sẵn trong Ruby sử dụng mô-đun [Pty] (http://www.ruby-doc.org/stdlib-1.9.3/libdoc/pty/rdoc/PTY.html) tích hợp sẵn của nó . –

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

Phương pháp sử dụng nhiều nhất là dùng Open3 đây là mã của tôi phiên bản mã trên thay đổi nội dung với một số điều chỉnh:

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 
Các vấn đề liên quan