Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

วิธีออกจากโปรแกรม Ruby

ในฐานะนักพัฒนา เราใช้เวลามากมายในการทำให้โปรแกรมของเราทำงานจนมองข้ามไปได้ง่าย ๆ ว่าโปรแกรมเหล่านั้นจะออกอย่างไร และที่สำคัญ! เมื่อโปรแกรมของคุณทำงานอย่างถูกต้องเมื่อออก จะทำให้จัดการได้ง่ายขึ้นมาก และทำให้มีแนวโน้มที่จะทำงานกับเครื่องมือ 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 ในทางที่ผิดหรือไม่