`{{(ออก 1) อะไร ทางออก 1; }; } `หมายถึงอะไร


28

ผมยกมาข้อมูลโค้ดต่อไปจากที่สร้างขึ้นโดยconfig.statusconfigure

if test ! -f "$as_myself"; then
{ { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
{ (exit 1); exit 1; }; }
fi

ในข้อมูลโค้ดจะ{ (exit 1); exit 1; };ทำอย่างไร จุดประสงค์ของการทำเพียงแค่exitใน subshell คืออะไร

คำตอบ:


33

การดำเนินการ(exit 1);เป็นวิธีที่ง่ายที่สุดในการเรียกERRกับดัก มันจะทริกเกอร์ทางออกทันทีหากset -eมีผล (การทริกเกอร์เงื่อนไขข้อผิดพลาดจำเป็นต้องมีคำสั่งล้มเหลวexitด้วยค่าความล้มเหลวใน subshell ทำให้ subshell ล้มเหลว)

exit 1; จะไม่ทำสิ่งเหล่านั้น

ดังนั้น{(exit 1); exit 1;}สามารถใช้เพื่อสร้างERRกับดักก่อนซึ่งอาจทำสิ่งที่มีประโยชน์สำหรับวัตถุประสงค์ในการดีบั๊กและยุติสคริปต์ด้วยตัวบ่งชี้ข้อผิดพลาด

แต่นั่นไม่ใช่สิ่งที่เกิดขึ้นในautoconfไฟล์ autoconfสคริปต์พึ่งพากับEXITดักเพื่อทำความสะอาดไฟล์ชั่วคราวที่สร้างขึ้นระหว่างการรัน เชลล์ส่วนใหญ่รวมถึงbashจะตั้งค่าสถานะจากค่าที่ให้ไว้ในexitคำสั่งก่อนที่จะเรียกEXITกับดัก ซึ่งอาจทำให้EXITแทร็บตรวจพบว่ามีการเรียกใช้จากข้อผิดพลาดหรือจากการเลิกจ้างตามปกติและยังช่วยให้มั่นใจได้ว่าสถานะทางออกถูกตั้งค่าอย่างถูกต้องในตอนท้ายของการดำเนินการกับดัก

อย่างไรก็ตามดูเหมือนว่าบางเชลล์ไม่ได้ทำงานร่วมกัน นี่คือคำพูดจากautoconfคู่มือ :

เชลล์สคริปต์บางตัวเช่นที่สร้างโดยautoconfใช้กับดักเพื่อล้างข้อมูลก่อนออก หากคำสั่งเชลล์สุดท้ายออกด้วยสถานะที่ไม่ใช่ศูนย์กับดักยังออกด้วยสถานะที่ไม่ใช่ศูนย์เพื่อให้ผู้เรียกใช้สามารถบอกได้ว่าเกิดข้อผิดพลาดขึ้น

น่าเสียดายที่ในบางเชลล์เช่น Solaris /bin/shกับดักออกจะไม่สนใจอาร์กิวเมนต์ของคำสั่ง exit ในเชลล์เหล่านี้กับดักไม่สามารถระบุได้ว่ามันถูกเรียกใช้โดย exit ธรรมดาหรือโดย exit 1 แทนการเรียก exit โดยตรงให้ใช้AC_MSG_ERRORแมโครที่มีวิธีแก้ปัญหาสำหรับปัญหานี้

วิธีแก้ปัญหาคือเพื่อให้แน่ใจว่า$?มีสถานะการออกก่อนที่exitคำสั่งจะถูกดำเนินการเพื่อที่จะมีค่านั้นอย่างแน่นอนเมื่อเรียกใช้EXITกับดัก และแน่นอนว่ามันเป็นAC_MSG_ERRORมาโครที่แทรกโค้ดแปลก ๆ นั้นพร้อมกับเครื่องหมายวงเล็บซ้ำซ้อน


ทำไมไม่เพียงแค่ดำเนินการfalseแทน(exit 1)?
Ruslan

3
@ Ruslan: สองปัญหา (1) สิ่งสำคัญที่สุด: falseไม่อนุญาตให้คุณตั้งค่ารหัสสถานะและไม่มีการรับประกันว่าจะส่งคืนสถานะที่ไม่ใช่ศูนย์ใด (2) falseไม่ใช่ builtin ในตัวดังนั้นจึงต้องใช้กระบวนการลูก ในทางตรงกันข้าม, (exit 1)หอยส่วนใหญ่สามารถหลีกเลี่ยงการวิ่งพล่านเด็กที่จะจัดการ
rici

8

ไม่มีจุดประสงค์สำหรับสิ่งนี้เท่าที่ฉันเห็นไม่มีอะไรที่สามารถทำได้โดยตรงโดยเริ่มจาก subshell แล้วออกทันที

สิ่งต่าง ๆ เช่นนี้น่าจะเป็นผลข้างเคียงของการสร้างรหัสโดยอัตโนมัติ - ในบางกรณีอาจมีคำสั่งอื่นดำเนินการใน subshell ที่มีexit 1เหตุผล ในท้ายที่สุดมีโอกาสที่ดีที่รหัสการสร้างจะง่ายขึ้นด้วยการอนุญาตให้แทรกคำสั่งที่ไม่มีฟังก์ชั่นใด ๆ ในบางกรณีและสร้าง 'รหัสที่สะอาด' ทุกครั้งมีความซับซ้อนมากขึ้น ไม่ว่าจะเป็นหรือรหัสที่สร้างด้านบนเป็นเพียงเขียนไม่ดี :)

การใช้เสรี{...}เป็นอีกตัวอย่างหนึ่งของสิ่งนี้ส่วนใหญ่เป็นแบบซ้ำซ้อน แต่มันง่ายกว่าที่จะเขียนโค้ดที่แทรกไว้ในทุกกรณี (อาจเป็นในบางคนที่คุณต้องการเปลี่ยนทิศทางเอาต์พุต / อินพุตของบล็อก) แทนที่จะแยกแยะ สิ่งที่พวกเขาไม่ต้องการและละเว้นพวกเขา


มันมีจุดประสงค์ ดูคำตอบของ @ rici
โปรเก่า

1

(exit 1)เป็นวิธีที่ง่ายและน่าจะง่ายที่สุดในการรับรหัสทางออกที่แน่นอน (ในกรณีพิเศษที่ 1 มีวิธีที่ง่ายกว่าแน่นอน) แต่นั่นไม่ใช่เหตุผลในกรณีนี้เนื่องจากไม่มีการตรวจสอบรหัสออก

วัตถุประสงค์ของการวางexitใน subshell อาจจะไม่ออกจากสคริปต์ (แม้ว่าจะใช้ exit สำหรับการสร้างรหัสการออกที่แน่นอน)

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