<ก่อนหน้านี้ | Contents | ถัดไป>
การเขียนโปรแกรมป้องกัน
สิ่งสำคัญคือต้องตรวจสอบสมมติฐานเมื่อตั้งโปรแกรม นี่หมายถึงการประเมินสถานะการออกของโปรแกรมและคำสั่งที่ใช้โดยสคริปต์อย่างรอบคอบ นี่คือตัวอย่างที่สร้างจากเรื่องจริง ผู้ดูแลระบบที่โชคร้ายคนหนึ่งได้เขียนสคริปต์เพื่อดำเนินการบำรุงรักษาบนเซิร์ฟเวอร์ที่สำคัญ สคริปต์ประกอบด้วยรหัสสองบรรทัดต่อไปนี้:
ซีดี $dir_name rm *
ซีดี $dir_name rm *
ไม่มีอะไรผิดปกติกับสองบรรทัดนี้ ตราบใดที่ไดเร็กทอรีที่มีชื่ออยู่ในตัวแปร dir_nameมีอยู่. แต่เกิดอะไรขึ้นถ้ามันไม่? ในกรณีนั้น cd คำสั่งล้มเหลวและสคริปต์จะไปยังบรรทัดถัดไปและลบไฟล์ในไดเร็กทอรีการทำงานปัจจุบัน ไม่ใช่ผลลัพธ์ที่ต้องการเลย! ผู้ดูแลระบบที่โชคร้ายได้ทำลายส่วนสำคัญของเซิร์ฟเวอร์เนื่องจากการตัดสินใจออกแบบนี้
มาดูวิธีปรับปรุงการออกแบบนี้กัน ประการแรก เป็นการดีที่จะทำการประหารชีวิต rm ขึ้นอยู่กับความสำเร็จของ cd:
cd $dir_name && rm *
cd $dir_name && rm *
ด้วยวิธีนี้หาก cd คำสั่งล้มเหลว the rm คำสั่งไม่ได้ดำเนินการ จะดีกว่านี้ แต่ยังคงปล่อยให้เปิดโอกาสที่ตัวแปร dir_name, ไม่ได้ตั้งค่าหรือว่างเปล่า ซึ่งจะทำให้ไฟล์ในโฮมไดเร็กทอรีของผู้ใช้ถูกลบ นอกจากนี้ยังสามารถหลีกเลี่ยงได้โดยการตรวจสอบเพื่อดูว่า dir_name มีชื่อของไดเร็กทอรีที่มีอยู่จริง:
[[ -d $dir_name ]] && cd $dir_name && rm *
[[ -d $dir_name ]] && cd $dir_name && rm *
บ่อยครั้ง เป็นการดีที่สุดที่จะรวมตรรกะในการยุติสคริปต์และรายงานข้อผิดพลาดเมื่อเกิดสถานการณ์ดังที่กล่าวข้างต้น:
# ลบไฟล์ในไดเร็กทอรี $dir_name if [[ ! -d "$dir_name" ]]; แล้ว
echo "ไม่มีไดเรกทอรีดังกล่าว: '$dir_name'" >&2 ออก 1
fi
ถ้า ! ซีดี $dir_name; แล้ว
echo "ไม่สามารถ cd เป็น '$dir_name'" >&2 ออก 1
fi
ถ้า ! rm *; แล้ว
echo "การลบไฟล์ล้มเหลว ตรวจสอบผลลัพธ์" >&2 ออก 1
fi
# ลบไฟล์ในไดเร็กทอรี $dir_name if [[ ! -d "$dir_name" ]]; แล้ว
echo "ไม่มีไดเรกทอรีดังกล่าว: '$dir_name'" >&2 ออก 1
fi
ถ้า ! ซีดี $dir_name; แล้ว
echo "ไม่สามารถ cd เป็น '$dir_name'" >&2 ออก 1
fi
ถ้า ! rm *; แล้ว
echo "การลบไฟล์ล้มเหลว ตรวจสอบผลลัพธ์" >&2 ออก 1
fi
ในที่นี้ เราตรวจสอบทั้งชื่อ เพื่อดูว่าเป็นชื่อไดเร็กทอรีที่มีอยู่ และชื่อ suc-
ข้อผิดพลาดเชิงตรรกะ
เซสของ cd สั่งการ. หากไม่สำเร็จ ข้อความแสดงข้อผิดพลาดเชิงพรรณนาจะถูกส่งไปยังข้อผิดพลาดมาตรฐาน และสคริปต์จะสิ้นสุดด้วยสถานะการออกหนึ่งสถานะเพื่อบ่งชี้ความล้มเหลว