2013-09-10 37 views
74

Tôi có một loạt các cuộc gọi hệ thống trong ruby ​​như sau và tôi muốn kiểm tra mã thoát của chúng đồng thời để tập lệnh của tôi thoát ra nếu lệnh đó không thành công.lệnh hệ thống ruby ​​kiểm tra mã thoát

system("VBoxManage createvm --name test1") 
system("ruby test.rb") 

Tôi muốn một cái gì đó giống như

system("VBoxManage createvm --name test1", 0) < - nơi tham số thứ hai kiểm tra mã lối ra và khẳng định rằng cuộc gọi hệ thống đã thành công, và nếu không, nó sẽ nâng cao một lỗi hay làm điều gì đó của loại đó.

Có thể không?

Tôi đã thử điều gì đó dọc theo dòng này và điều đó cũng không hoạt động.

system("ruby test.rb") 
system("echo $?") 

hoặc

`ruby test.rb` 
exit_code = `echo $?` 
if exit_code != 0 
    raise 'Exit code is not zero' 
end 
+2

thể trùng lặp của [lỗi Bắt dòng lệnh sử dụng% x] (http://stackoverflow.com/questions/4771930/catching-command-line-errors-using-x) –

+0

Ở phía trên ví dụ, 'exit_code' sẽ là một chuỗi - hoặc' "0 \ n" 'hoặc' "1 \ n" ', vì vậy' exit_code! = 0' sẽ luôn là đúng – dgmstuart

Trả lời

129

Từ documentation:

hệ thống trả về true nếu lệnh cho zero trạng thái thoát, false cho tình trạng không lối ra không. Trả về nil nếu thực hiện lệnh không thành công.

system("unknown command")  #=> nil 
system("echo foo")   #=> true 
system("echo foo | grep bar") #=> false 

Hơn nữa

Một trạng thái lỗi có sẵn trong $?.

system("VBoxManage createvm --invalid-option") 

$?    #=> #<Process::Status: pid 9926 exit 2> 
$?.exitstatus #=> 2 
+1

và cách nắm bắt đầu ra của nó (không phải mã thoát) thành một biến? –

+2

@ alexander-supertramp xem http://stackoverflow.com/q/690151/477037 – Stefan

+0

Nếu bạn đang ở trong một bảng điều khiển đường ray, hãy thử nghiệm điều này, chỉ cần nhớ rằng bạn có thể mất giá trị của $? vì vậy bạn cần phải nắm bắt nó như là một phần của lệnh REPL của bạn '[10] pry (chính)> hệ thống (" chạm/root/test 2>/dev/null ") => false [11] pry (main)> $ ?. exitstatus => 0 [12] pry (chính)> hệ thống ("chạm/root/test 2>/dev/null"); $ ?. exitstatus => 1' – lardcanoe

21

system lợi nhuận false nếu lệnh có một mã thoát khác không, hoặc nil nếu không có lệnh.

Do đó

system("foo") or exit 

hoặc

system("foo") or raise "Something went wrong with foo" 

nên làm việc, và là một cách hợp lý súc tích.

5

Bạn sẽ không nắm bắt được kết quả của system cuộc gọi của bạn, đó là nơi mà các mã kết quả được trả về:

exit_code = system("ruby test.rb") 

Ghi mỗi system cuộc gọi hoặc tương đương, trong đó bao gồm các backtick-phương pháp, sinh ra một lớp vỏ mới , vì vậy không thể nắm bắt được kết quả của môi trường hệ vỏ trước đó. Trong trường hợp này, exit_codetrue nếu mọi thứ hoạt động, nil nếu không.

Lệnh popen3 cung cấp chi tiết cấp thấp hơn.

+2

['Open3.capture3'] (http://www.ruby-doc.org/stdlib-2.0.0/libdoc/open3/rdoc/Open3.html#method-c-capture3) là một phương pháp đặc biệt dễ sử dụng cho loại tác vụ này. –

+2

exit_code có lẽ không phải là tên tốt nhất cho nó – drewish

3

Một cách để làm điều này là chuỗi chúng bằng cách sử and hoặc &&:

system("VBoxManage createvm --name test1") and system("ruby test.rb") 

Cuộc gọi thứ hai sẽ không thể chạy nếu là người đầu tiên thất bại.

Bạn có thể bọc những người trong một if() để cung cấp cho bạn một số dòng điều khiển:

if (
    system("VBoxManage createvm --name test1") && 
    system("ruby test.rb") 
) 
    # do something 
else 
    # do something with $? 
end 
15

Đối với tôi, tôi thích sử dụng '' để gọi các lệnh shell và kiểm tra $? để có được trạng thái xử lý. $? là đối tượng trạng thái quy trình, bạn có thể lấy thông tin quy trình của lệnh từ đối tượng này, bao gồm: mã trạng thái, trạng thái thực thi, pid, v.v.

Một số phương pháp hữu ích của $? đối tượng:

$?.exitstatus => return error code  
    $?.success? => return true if error code is 0, otherwise false 
    $?.pid => created process pid 
Các vấn đề liên quan