kiểm tra lệnh hệ thống ruby ​​mã thoát


106

Tôi có một loạt lệnh gọi hệ thống trong ruby ​​chẳng hạn như lệ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.

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) <- trong đó tham số thứ hai kiểm tra mã thoát và xác nhận rằng lệnh gọi hệ thống đó đã thành công, và nếu không, nó sẽ phát sinh lỗi hoặc thực hiện điều gì đó tương tự.

Liệu có thể không?

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

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

hoặc là

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


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

Câu trả lời:


166

Từ tài liệu :

hệ thống trả về truenếu lệnh cho trạng thái thoát bằng không, falseđối với trạng thái thoát khác không. Trả về nilnếu thực thi 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

2
và làm thế nào để nắm bắt đầu ra của nó (không phải mã thoát) cho một biến?
ア レ ッ ク ス

Nếu bạn đang sử dụng bảng điều khiển rails, thử nghiệm điều này, chỉ cần lưu ý 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ư một phần của REPL bạn lệnh [10] pry(main)> system("touch /root/test 2> /dev/null") => false [11] pry(main)> $?.exitstatus => 0 [12] pry(main)> system("touch /root/test 2> /dev/null"); $?.exitstatus => 1
lardcanoe

Một so sánh tuyệt vời khác về system, backticks %xexecđược cung cấp tại đây: stackoverflow.com/questions/6338908/…
Tom Harrison

38

Đố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 quy trình. $? là một đố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 $? vật:

   $?.exitstatus => return error code    
   $?.success? => return true if error code is 0, otherwise false
   $?.pid => created process pid

1
Với sự giúp đỡ của Rubocop, tôi phát hiện ra rằng các bí danh có thể đọc được cho $?$CHILD_STATUS
RajaRaviVarma

26

systemtrả về falsenếu lệnh có mã thoát khác 0 hoặc nilnếu không có lệnh.

vì thế

system( "foo" ) or exit

hoặc là

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

sẽ hoạt động và ngắn gọn hợp lý.


6

Bạn không nắm bắt được kết quả systemcuộc gọi của mình , đây là nơi mã kết quả được trả về:

exit_code = system("ruby test.rb")

Hãy nhớ mỗi systemlệnh gọi hoặc tương đương, bao gồm cả phương thức backtick sinh ra một trình bao mới, vì vậy không thể nắm bắt kết quả của môi trường của trình bao trước đó. Trong trường hợp exit_codenày là truenếu mọi thứ diễn ra tốt đẹp, nilngược lại.

Các popen3lệnh cung cấp nhiều chi tiết ở mức độ thấp.


2
Open3.capture3là một phương pháp đặc biệt dễ sử dụng cho loại nhiệm vụ này.
the Tin Man

6

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

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

Cuộc gọi thứ hai sẽ không được chạy nếu cuộc gọi đầu tiên không thành công.

Bạn có thể bọc chúng trong một if ()để cung cấp cho bạn một số điều khiển luồng:

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

Đây là điều tôi muốn đạt được cho đến nay, đủ thẳng thắn và rõ ràng. Cảm ơn bạn
mochadwi
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.