ฉันสังเกตเห็นพฤติกรรมแปลก ๆ บางอย่างเมื่อใช้set -e
( errexit
), set -u
( nounset
) พร้อมกับดัก ERR และ EXIT ดูเหมือนว่าพวกเขาเกี่ยวข้องกันดังนั้นการใส่คำถามเหล่านั้นลงในคำถามเดียวก็สมเหตุสมผล
1) set -u
ไม่เรียกใช้กับดัก ERR
รหัส:
#!/bin/bash trap 'echo "ERR (rc: $?)"' ERR set -u echo ${UNSET_VAR}
- คาดว่า: มีการเรียกใช้กับดัก ERR, RC! = 0
- จริง: ไม่ได้เรียกกับแทร็บ ERR , RC == 1
- หมายเหตุ:
set -e
ไม่เปลี่ยนผลลัพธ์
2) การใช้set -eu
รหัสออกในกับดักของ EXIT คือ 0 แทนที่จะเป็น 1
รหัส:
#!/bin/bash trap 'echo "EXIT (rc: $?)"' EXIT set -eu echo ${UNSET_VAR}
- คาดว่า: EXIT กับดักถูกเรียกRC == 1
- จริง: ออกจากกับดักเรียกว่าRC == 0
- หมายเหตุ: เมื่อใช้
set +e
RC == 1. แทร็ก EXIT จะส่งคืน RC ที่เหมาะสมเมื่อคำสั่งอื่นส่งข้อผิดพลาด - แก้ไข:มีโพสต์ SO ในหัวข้อนี้ที่มีความคิดเห็นที่น่าสนใจแนะนำว่านี่อาจเกี่ยวข้องกับเวอร์ชัน Bash ที่ใช้อยู่ ทดสอบตัวอย่างข้อมูลนี้ด้วย Bash 4.3.11 ให้ผลเป็น RC = 1 ดีกว่า น่าเสียดายที่การอัปเกรด Bash (จาก 3.2.51) ในโฮสต์ทั้งหมดเป็นไปไม่ได้ในขณะนี้ดังนั้นเราจึงต้องหาวิธีแก้ปัญหาอื่น ๆ
ใครสามารถอธิบายพฤติกรรมเหล่านี้ได้บ้าง
การค้นหาหัวข้อเหล่านี้ไม่ประสบความสำเร็จมากซึ่งค่อนข้างน่าแปลกใจเนื่องจากจำนวนโพสต์ในการตั้งค่า Bash และกับดัก มีเธรดฟอรัมหนึ่งหัวข้อแต่ข้อสรุปค่อนข้างไม่พอใจ
set -e
และset -u
ได้รับการออกแบบมาเป็นพิเศษเพื่อฆ่าเชลล์สคริปต์ การใช้พวกเขาในสภาวะที่อาจทำให้แอปพลิเคชันของพวกเขาจะฆ่าเชลล์สคริปต์ ไม่มีสิ่งใดมาขวางกั้นได้นอกจากจะไม่ใช้มันและเพื่อทำการทดสอบแทนเงื่อนไขเหล่านั้นเมื่อนำไปใช้ในลำดับของรหัส set -eu
ดังนั้นโดยทั่วไปคุณสามารถเขียนดีเปลือกรหัสหรือคุณสามารถใช้
-u
จะไม่เรียกใช้กับดัก ERR (มันเป็นข้อผิดพลาดดังนั้นจึงไม่ควรเรียกกับดัก) หรือรหัสข้อผิดพลาดคือ 0 แทน 1 หลังดูเหมือนจะเป็นข้อผิดพลาดสิ่งที่ได้รับการแก้ไขในรุ่นที่ใหม่กว่าดังนั้นนั่นคือ แต่ส่วนแรกค่อนข้างยากที่จะเข้าใจหากคุณไม่ได้ตระหนักว่าข้อผิดพลาดในการประเมินเชลล์ (การขยายพารามิเตอร์) และข้อผิดพลาดจริงในคำสั่งนั้นดูเหมือนจะเป็นสองสิ่งที่แตกต่างกัน สำหรับวิธีการแก้ปัญหาที่คุณแนะนำคือตอนนี้ฉันกำลังพยายามหลีกเลี่ยง-eu
และตรวจสอบด้วยตนเองเมื่อจำเป็น
(set -u; : $UNSET_VAR)
และที่คล้ายกัน สิ่งต่าง ๆ เช่นนี้ก็ดีเช่นกัน - คุณสามารถทำอะไรหลาย ๆ อย่าง&&
ได้(set -e; mkdir dir; cd dir; touch dirfile)
บ้าง: ถ้าคุณได้ดริฟท์ของฉัน เป็นเพียงว่าสิ่งเหล่านั้นถูกควบคุมบริบท - เมื่อคุณตั้งค่าเป็นตัวเลือกระดับโลก มักจะมีวิธีแก้ปัญหาที่มีประสิทธิภาพมากกว่า
bash
ยากจนกับมาตรฐานและเริ่มวางกับดักใน subshells กับดักควรถูกประหารชีวิตในสภาพแวดล้อมเดียวกันจากที่ใดที่มันกลับมา แต่bash
ก็ไม่ได้ทำแบบนั้นสักพัก