Chạy lệnh dòng lệnh trong tập lệnh Ruby


92

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ố gắng tạo một chương trình Ruby nhỏ có thể quay ra và nhận / gửi thông qua các chương trình dòng lệnh như 'screen', 'rcsz', v.v.

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


Có thể có bản sao của Lệnh gọi shell từ Ruby
ymoreau 17/08/2018

Câu trả lời:


209

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


a. Sử dụng %xhoặ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)

Các phương thức này sẽ trả về stdout và chuyển hướng stderr đến 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 thức này trả về truenếu lệnh thành công. Nó chuyển hướng tất cả đầu ra đến 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.

Điều đó thay thế quy trình hiện tại bằng quy trình được tạo 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 thức này không đợi quá trình thoát 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 thức này sẽ trả về một IOđối tượng đánh giá lại đầu vào / đầu ra của quy trình mới. Đây cũng là cách duy nhất tôi biết để cung cấp đầu vào cho chương trình.


f. Sử dụng Open3(trên 1.9.2 trở lên)

require 'open3'

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

Open3có 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 cung cấp cho bạn quyền truy cập vào stderr.


Mẹo thưởng : io = IO.popen 'cat > out.log', 'r+'; ghi kết quả đầu ra của lệnh vào "out.log"
Narfanator

1
Ưu điểm và khuyết điểm của từng loại là gì. Làm cách nào để quyết định sử dụng? Còn việc sử dụng FileUtils[ ruby-doc.org/stdlib-1.9.3/libdoc/fileutils/rdoc/FileUtils.html] thì sao?
Ava

1
Tôi đang thực hiện một lệnh SVN bằng thực thi. Tôi không muốn đầu ra của tệp thực thi xuất hiện trên bảng điều khiển. Tôi muốn chuyển hướng nó để có thể lưu trữ nó dưới dạng một biến và thực hiện một số xử lý về điều này. Tôi phải làm nó như thế nào ?
stack1

2
trạng thái. thành công? không còn hoạt động đối với tôi trên ruby ​​2.4, nó đã thay đổi thành trạng thái. thành công? :)
DanielG

14

Có một số 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 thực sự cần thực hiện đầu vào và đầu ra với stdin / stdout của lệnh, có thể bạn sẽ muốn xem xét IO::popenphương thức, phương pháp này cung cấp cơ sở cụ thể.


popen hoạt động tốt nếu ứng dụng của bạn đạt tiêu chuẩn. Nếu bạn cần sự tương tác nhiều hơn hoặc muốn làm một cái gì đó khác nhau với stdout, stdin, và đặc biệt là thiết bị lỗi chuẩn bạn cũng sẽ muốn nhìn vào 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

Có, điều này chắc chắn có thể làm được nhưng phương pháp thực hiện khác nhau tùy thuộc vào việc chương trình "dòng lệnh" được đề cập hoạt động ở 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 hệ thống / thực thi.

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. Đố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 "kỳ vọng". Điều này sẽ cho phép bạn viết kịch bản những gì bạn muốn thấy trên màn hình và những gì sẽ gửi khi bạ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 có thể nên xem xét những gì bạn đang cố gắng đạt được và tìm thư viện / viên ngọc có liên quan để làm điều đó thay vì cố gắng tự động hóa một ứng dụng toàn màn hình hiện có. Ví dụ: " Cần hỗ trợ với giao tiếp cổng nối tiếp trong Ruby " liên quan đến giao tiếp Cổng nối tiếp, một con trỏ trước để quay số nếu đó là điều 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.


Một phiên bản đơn giản của Expect có sẵn trong Ruby bằng cách sử dụng mô-đun Pty tích hợp của nó .
the Tin Man

0

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

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.