ในฐานะนักพัฒนา เราใช้เวลามากมายในการทำให้โปรแกรมของเราทำงานจนมองข้ามไปได้ง่าย ๆ ว่าโปรแกรมเหล่านั้นจะออกอย่างไร และที่สำคัญ! เมื่อโปรแกรมของคุณทำงานอย่างถูกต้องเมื่อออก จะทำให้จัดการได้ง่ายขึ้นมาก และทำให้มีแนวโน้มที่จะทำงานกับเครื่องมือ devops มาตรฐานมากขึ้น
มีหลายวิธีที่คุณสามารถออกจากโปรแกรม Ruby ได้ ฉันได้แสดงบางส่วนของพวกเขาด้านล่าง ในโพสต์นี้ เราจะพูดถึงรายละเอียดของแต่ละสิ่งเหล่านี้ และวิธีที่สามารถใช้เพื่อทำให้แอปของคุณเป็นพลเมืองยูนิกซ์ที่มีมารยาทดี
# You can exit by calling a method
exit
exit!
abort("She cannot take any more of this, Captain!")
# ...or by failing to catch an exception
raise("Destroyed...")
fail
# ...or by letting the program end naturally. :)
รหัสออก และคุณ
ทุกโปรแกรมที่คุณเรียกใช้บน Linux และ OSX จะส่งคืนรหัสสถานะการออกเมื่อทำงานเสร็จแล้ว ปกติคุณจะไม่เห็นรหัสทางออก ระบบปฏิบัติการเบื้องหลังใช้เพื่อตรวจสอบว่าโปรแกรมออกจากการทำงานตามปกติหรือมีข้อผิดพลาดหรือไม่
หากคุณกำลังใช้ bash คุณสามารถดูรหัสทางออกของโปรแกรมที่คุณเพิ่งเรียกใช้โดยตรวจสอบ $?
ตัวแปรสภาพแวดล้อม ตัวอย่างด้านล่างแสดงรหัสทางออกสำหรับความล้มเหลว จากนั้นเพื่อความสำเร็จ
% ls this-file-doesnt-exist
ls: this-file-doesnt-exist: No such file or directory
blog% echo $?
1
% ls .
bm.rb
% echo $?
0
โดยทั่วไป กฎสำหรับระบบที่ใช้ยูนิกซ์คือศูนย์หมายถึงความสำเร็จ ไม่ใช่ศูนย์หมายถึงความล้มเหลว
หากคุณเคยใช้ &&
"ตัวดำเนินการ" ใน bash แสดงว่าคุณใช้รหัสสถานะแล้ว ในตัวอย่างด้านล่าง เราบอกให้ bash รันโปรแกรม B ต่อเมื่อโปรแกรม A สำเร็จเท่านั้น
% a && b
คุณสามารถใช้เคล็ดลับนี้ได้หลายวิธี ตัวอย่างเช่น คุณอาจต้องการคอมไพล์เนื้อหาล่วงหน้า และอัปโหลดไปยัง CDN
blog% rake assets:precompile && rake cdn:upload_assets
การระบุสถานะการออกด้วย Ruby
Ruby ดูแลสถานะการออกของเรามากมาย หากโปรแกรมของคุณออกตามปกติ โปรแกรมจะส่งคืนสถานะ "สำเร็จ" หากล้มเหลวเนื่องจากข้อยกเว้นที่ไม่ถูกตรวจจับ จะทำให้สถานะ "ล้มเหลว" ด้านล่างฉันกำลังแสดงรหัสทางออกสำหรับสคริปต์ที่ทำให้เกิดข้อยกเว้น
% ruby err.rb
err.rb:1:in `<main>': goodbye (RuntimeError)
tmp% echo $?
1
แต่ถ้าคุณไม่ต้องการข้อยกเว้นที่ไม่ถูกตรวจจับล่ะ จะทำอย่างไรถ้าคุณต้องการออกอย่างหมดจด แต่ยังคงส่งคืนรหัสข้อผิดพลาด "ล้มเหลว" ยิ่งไปกว่านั้น ถ้าคุณต้องการส่งคืนรหัสที่กำหนดเองพร้อมข้อความแสดงข้อผิดพลาดล่ะ
โชคดีที่มันค่อนข้างง่าย เพียงส่งอาร์กิวเมนต์ไปที่ exit
การทำงาน. อาร์กิวเมนต์อาจเป็นบูลีนหรือจำนวนเต็ม หากเป็นบูลีน ความจริงก็คือความสำเร็จ หากเป็นจำนวนเต็มมากกว่า 0 แสดงว่าสำเร็จ
exit(true) # Exits with "success" code
exit(0) # Exits with "success" code
exit(false) # Exits with "failure" code
exit(1) # Exits with "failure" code
exit(436) # Custom failure error code
วิธี exit
ทำงานภายใต้ประทุน
วิธีการออกเพียงแค่ยก SystemExit
ข้อยกเว้น หากไม่มีการตรวจพบ โปรแกรมจะยกเลิกเช่นเดียวกับที่ทำกับข้อยกเว้นอื่นๆ ที่ไม่ได้รับการตรวจจับ ดีมาก แต่มีผลที่น่าสนใจบางอย่าง
หากคุณจะกลืนข้อยกเว้น SystemExit ทั้งหมด คุณจะทำลายวิธีการออก ฉันได้แสดงในตัวอย่างด้านล่างแล้ว
begin
exit 100
rescue SystemExit => e
puts "Tried to exit with status #{ e.status }"
end
puts "...but it never exited, because we swallowed the exception"
# Outputs:
# Tried to exit with status 100
# ...but it never exited, because we swallowed the exception
นี่เป็นอีกเหตุผลหนึ่งที่จะไม่ช่วยเหลือ Exception
. เพราะ SystemExit
รับช่วงจาก Exception
, กลืน Exception
จะทำให้ทางออกพัง
begin
exit
rescue Exception # never do this
puts "I just broke the exit function!"
end
ข้อความแสดงข้อผิดพลาดที่มนุษย์อ่านได้
แม้ว่ารหัสทางออกจะดีสำหรับเครื่องจักร แต่มนุษย์เรามักชอบข้อความอธิบายเล็กน้อย โชคดีที่ระบบปฏิบัติการมีสตรีมเอาต์พุตสำหรับสิ่งต่างๆ เช่น ข้อความแสดงข้อผิดพลาดโดยเฉพาะ ใช่ ฉันกำลังพูดถึง STDERR
คุณสามารถเขียนถึง STDERR ได้เหมือนกับที่คุณเขียนไปยังอ็อบเจกต์ IO ใดๆ ในตัวอย่างด้านล่าง ฉันกำลังเขียนข้อความแสดงข้อผิดพลาดและออกโดยมีสถานะ "ข้อผิดพลาด"
STDERR.puts("ABORTED! You forgot to BAR the BAZ")
exit(false)
เนื่องจาก Ruby มีวิธีการเขียนที่รัดกุมกว่าใน stdout และออกด้วยรหัสข้อผิดพลาด เพียงใช้ abort
วิธีการ
# Write the message to STDERR and exit with an error status code.
abort("ABORTED! You forgot to BAR the BAZ")
โทรกลับผ่าน at_exit
Ruby ให้คุณลงทะเบียนตัวจัดการซึ่งสามารถเรียกได้ทุกครั้งที่ออกจากโปรแกรม สามารถมีได้มากกว่าหนึ่งรายการ - พวกเขาถูกเรียกในลำดับที่ตรงกันข้ามกับที่พวกเขาลงทะเบียน นี่คือลักษณะ:
at_exit do
puts "handler 1"
end
at_exit do
puts "handler 2"
end
# Outputs "handler2\nhandler1" on exit
ตัวจัดการทางออกสามารถแทนที่รหัสทางออกได้ คุณทำได้โดยเรียก exit จากภายใน handler แม้ว่าดูเหมือนว่าสิ่งนี้จะทำให้เกิดลูปอนันต์ แต่ก็ไม่เป็นเช่นนั้น :)
at_exit do
exit 100
end
exit 0
# This program exits with a code of 100
หากคุณต้องการออกโดยไม่โทรกลับ คุณสามารถทำได้โดยใช้ exit!
กระบวนการ. แต่พึงระลึกไว้เสมอว่าสิ่งนี้อาจทำให้เกิดปัญหาหากคุณมี gem หรือรหัสบุคคลที่สามอื่นๆ ที่ขึ้นอยู่กับการเรียกกลับเหล่านั้น
ส่วนที่น่าสนใจ
ปรากฎว่าห้องสมุดจำนวนมากใช้ at_exit
ในทางประดิษฐ์ - และบางคนอาจบอกว่าแฮ็ก - วิธี ตัวอย่างเช่น ซินาตราใช้ at_exit
ขอเป็นวิธีการบูตเว็บแอป ซึ่งช่วยให้มั่นใจได้ว่าโค้ดทั้งหมดของคุณได้รับการโหลดก่อนที่จะเริ่มเซิร์ฟเวอร์ นี่คือลักษณะ:
module Sinatra
class Application < Base
...
at_exit { Application.run! if $!.nil? && Application.run? }
end
มีโพสต์ดีๆ เกี่ยวกับเรื่องนี้ในบล็อก Arkency:เรากำลังใช้ at_exit ในทางที่ผิดหรือไม่