perintah sistem ruby ​​memeriksa kode keluar

106

Saya memiliki banyak panggilan sistem dalam ruby ​​seperti berikut dan saya ingin memeriksa kode keluar mereka secara bersamaan sehingga skrip saya keluar jika perintah itu gagal.

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

Saya ingin sesuatu seperti

system("VBoxManage createvm --name test1", 0) <- di mana parameter kedua memeriksa kode keluar dan menegaskan bahwa panggilan sistem berhasil, dan jika tidak, itu akan menimbulkan kesalahan atau melakukan sesuatu semacam itu.

Apakah itu mungkin?

Saya telah mencoba sesuatu di sepanjang garis ini dan itu tidak berhasil juga.

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

atau

`ruby test.rb`
exit_code = `echo $?`
if exit_code != 0
  raise 'Exit code is not zero'
end
pengguna1530318
sumber
2
kemungkinan duplikat dari Menangkap kesalahan baris perintah menggunakan% x
Sergio Tulentsev
Dalam contoh di atas, exit_codeakan menjadi string - baik "0\n"atau "1\n", jadi exit_code != 0akan selalu benar
dgmstuart

Jawaban:

166

Dari dokumentasi :

sistem kembali truejika perintah memberikan status keluar nol, falseuntuk status keluar bukan nol. Kembali niljika eksekusi perintah gagal.

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

Selanjutnya

Status kesalahan tersedia di $?.

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

$?             #=> #<Process::Status: pid 9926 exit 2>
$?.exitstatus  #=> 2
Stefan
sumber
2
dan bagaimana cara menangkap outputnya (bukan kode keluar) ke variabel?
ア レ ッ ク ス
Jika Anda berada di konsol rel, menguji ini, ingatlah bahwa Anda mungkin kehilangan nilai $? jadi Anda perlu menangkapnya sebagai bagian dari perintah REPL Anda [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
Perbandingan luar biasa lainnya dari system, backticks, %xdan execdisediakan di sini: stackoverflow.com/questions/6338908/…
Tom Harrison
38

Bagi saya, saya lebih suka menggunakan `` untuk memanggil perintah shell dan memeriksa $? untuk mendapatkan status proses. $? adalah objek status proses, Anda bisa mendapatkan informasi proses perintah dari objek ini, termasuk: kode status, status eksekusi, pid, dll.

Beberapa metode yang berguna dari $? obyek:

   $?.exitstatus => return error code    
   $?.success? => return true if error code is 0, otherwise false
   $?.pid => created process pid
Houcheng
sumber
1
Dengan bantuan Rubocop, saya menemukan bahwa alias yang dapat dibaca $?adalah$CHILD_STATUS
RajaRaviVarma
26

systemkembali falsejika perintah memiliki kode keluar bukan nol, atau niljika tidak ada perintah.

Karena itu

system( "foo" ) or exit

atau

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

harus berfungsi, dan cukup ringkas.

Neil Slater
sumber
6

Anda tidak menangkap hasil systempanggilan Anda , yang merupakan kode hasil dikembalikan:

exit_code = system("ruby test.rb")

Ingat setiap systempanggilan atau yang setara, yang menyertakan metode backtick, memunculkan shell baru, jadi tidak mungkin untuk menangkap hasil dari lingkungan shell sebelumnya. Dalam hal ini exit_codeadalah truejika semuanya berhasil, nilsebaliknya.

The popen3perintah menyediakan lebih rendah tingkat rinci.

anak laki-laki
sumber
2
Open3.capture3adalah metode yang sangat mudah digunakan untuk tugas semacam ini.
Tin Man
6

Salah satu cara untuk melakukannya adalah dengan merantai mereka menggunakan andatau &&:

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

Panggilan kedua tidak akan dijalankan jika yang pertama gagal.

Anda dapat membungkusnya if ()untuk memberi Anda kontrol aliran:

if (
  system("VBoxManage createvm --name test1") && 
  system("ruby test.rb")
) 
  # do something
else
  # do something with $?
end
Manusia Timah
sumber
Sejauh ini, inilah yang ingin saya capai, terus terang dan cukup jelas. Terima kasih
mochadwi