คำสั่งระบบทับทิมตรวจสอบรหัสทางออก


106

ฉันมีการเรียกระบบจำนวนมากในทับทิมดังต่อไปนี้และฉันต้องการตรวจสอบรหัสออกพร้อมกันเพื่อให้สคริปต์ของฉันออกหากคำสั่งนั้นล้มเหลว

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

ฉันต้องการสิ่งที่ชอบ

system("VBoxManage createvm --name test1", 0) <- โดยที่พารามิเตอร์ที่สองตรวจสอบรหัสออกและยืนยันว่าการเรียกระบบนั้นสำเร็จและหากไม่เป็นเช่นนั้นก็จะทำให้เกิดข้อผิดพลาดหรือทำอะไรบางอย่างในประเภทนั้น

เป็นไปได้หรือไม่

ฉันได้ลองทำตามแนวนี้แล้ว แต่ก็ไม่ได้ผลเช่นกัน

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

หรือ

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


ในตัวอย่างข้างต้นexit_codeจะเป็นสตริง - อย่างใดอย่างหนึ่ง"0\n"หรือ"1\n"ดังนั้นexit_code != 0จะเป็นจริงเสมอ
dgmstuart

คำตอบ:


166

จากเอกสารประกอบ :

ระบบจะส่งคืนtrueหากคำสั่งให้สถานะการออกเป็นศูนย์falseสำหรับสถานะการออกที่ไม่ใช่ศูนย์ ส่งคืนnilหากการดำเนินการคำสั่งล้มเหลว

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

นอกจากนี้

$?สถานะข้อผิดพลาดที่มีอยู่ใน

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

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

2
และจะจับเอาท์พุท (ไม่ใช่รหัสออก) ไปยังตัวแปรได้อย่างไร?
アレックス

หากคุณอยู่ในคอนโซลรางลองใช้สิ่งนี้โปรดทราบว่าคุณอาจสูญเสียมูลค่า $? ดังนั้นคุณต้องจับมันเป็นส่วนหนึ่งของคำสั่ง REPL ของคุณ [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

อีกหนึ่งการเปรียบเทียบที่ยอดเยี่ยมของsystembackticks %xและexecมีให้ที่นี่: stackoverflow.com/questions/6338908/…
Tom Harrison

38

สำหรับฉันฉันชอบใช้ `เพื่อเรียกคำสั่งเชลล์และตรวจสอบ $? เพื่อรับสถานะกระบวนการ $? เป็นอ็อบเจ็กต์สถานะกระบวนการคุณสามารถรับข้อมูลกระบวนการของคำสั่งจากอ็อบเจ็กต์นี้รวมถึง: โค้ดสถานะสถานะการดำเนินการ pid ฯลฯ

วิธีการที่มีประโยชน์บางอย่างของ $? วัตถุ:

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

1
ด้วยความช่วยเหลือของ Rubocop ฉันพบว่านามแฝงที่อ่านได้$?คือ$CHILD_STATUS
RajaRaviVarma

26

systemส่งคืนfalseหากคำสั่งมีรหัสออกที่ไม่ใช่ศูนย์หรือnilหากไม่มีคำสั่ง

ดังนั้น

system( "foo" ) or exit

หรือ

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

ควรใช้งานได้และมีความกระชับพอสมควร


6

คุณไม่ได้บันทึกผลลัพธ์ของการsystemโทรซึ่งเป็นที่ที่ส่งคืนรหัสผลลัพธ์:

exit_code = system("ruby test.rb")

จำการsystemเรียกแต่ละครั้งหรือเทียบเท่าซึ่งรวมถึง backtick-method ทำให้เกิดเชลล์ใหม่ดังนั้นจึงไม่สามารถจับผลลัพธ์ของสภาพแวดล้อมของเชลล์ก่อนหน้านี้ได้ ในกรณีนี้exit_codeคือtrueถ้าทุกอย่างได้ผลnilอื่น

popen3คำสั่งให้รายละเอียดในระดับต่ำมากขึ้น


2
Open3.capture3เป็นวิธีที่ง่ายโดยเฉพาะอย่างยิ่งสำหรับงานประเภทนี้
คนดีบุก

6

วิธีหนึ่งในการทำเช่นนี้คือการเชื่อมโยงโดยใช้andหรือ&&:

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

สายที่สองจะไม่ทำงานหากครั้งแรกล้มเหลว

คุณสามารถรวมสิ่งเหล่านี้ไว้ในif ()เพื่อให้คุณควบคุมการไหล:

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

นี่คือสิ่งที่ฉันต้องการบรรลุตรงไปตรงมาและชัดเจนเพียงพอ ขอบคุณ
mochadwi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.