คุณสามารถข้ามไปที่การแก้ไขด่วนได้ตลอดแต่นั่นไม่ใช่ตัวเลือกที่ดีที่สุด ดังนั้นฉันขอแนะนำให้อ่านทั้งหมดนี้ก่อน
rc.local
ไม่ทนต่อข้อผิดพลาด
rc.local
ไม่ได้ให้วิธีการกู้คืนอย่างชาญฉลาดจากข้อผิดพลาด หากคำสั่งใด ๆ ล้มเหลวคำสั่งจะหยุดทำงาน บรรทัดแรก#!/bin/sh -e
ทำให้มันถูกเรียกใช้งานในเชลล์ที่เรียกใช้ด้วย-e
แฟล็ก การ-e
ตั้งค่าสถานะเป็นสิ่งที่ทำให้สคริปต์ (ในกรณีนี้rc.local
) หยุดการทำงานในครั้งแรกที่คำสั่งล้มเหลวภายใน
คุณต้องการrc.local
ทำตัวแบบนี้ หากคำสั่งล้มเหลวคุณไม่ต้องการให้คำสั่งนั้นดำเนินการต่อด้วยคำสั่งเริ่มต้นอื่นใดก็ตามที่อาจต้องพึ่งพาคำสั่งนั้นหลังจากประสบความสำเร็จ
ดังนั้นหากคำสั่งใด ๆ ล้มเหลวคำสั่งที่ตามมาจะไม่ทำงาน ปัญหาที่นี่คือที่/script.sh
ไม่ได้ทำงาน (ไม่ว่ามันจะล้มเหลวดูด้านล่าง) ดังนั้นส่วนใหญ่คำสั่งบางอย่างก่อนที่มันจะล้มเหลว แต่อันไหน
มัน/bin/chmod +x /script.sh
คืออะไร
เลขที่
chmod
ทำงานได้ตลอดเวลา จัดให้มีระบบแฟ้มที่มีได้รับการติดตั้งคุณสามารถเรียกใช้/bin
/bin/chmod
และ/bin
ติดตั้งก่อนrc.local
วิ่ง
เมื่อรันในฐานะรูท/bin/chmod
ไม่ค่อยจะล้มเหลว มันจะล้มเหลวหากไฟล์ที่ทำงานนั้นเป็นแบบอ่านอย่างเดียวและอาจล้มเหลวหากระบบไฟล์นั้นเปิดอยู่ไม่ได้รับอนุญาต ไม่น่าจะมีที่นี่
โดยวิธีการsh -e
เป็นเหตุผลเดียวที่มันจะเป็นปัญหาหากchmod
ล้มเหลว เมื่อคุณเรียกใช้ไฟล์สคริปต์โดยการเรียกล่ามของมันอย่างชัดเจนมันไม่สำคัญว่าไฟล์นั้นจะถูกทำเครื่องหมายว่าปฏิบัติการหรือไม่ เฉพาะในกรณีที่มีการกล่าวว่า/script.sh
ไฟล์บิตที่เรียกใช้งานของไฟล์นั้นสำคัญ เนื่องจากมันบอกว่าsh /script.sh
มันไม่ได้ (ยกเว้นกรณีที่แน่นอน/script.sh
เรียกตัวเองในขณะที่มันทำงานซึ่งอาจล้มเหลวจากมันไม่ได้ปฏิบัติการ แต่มันไม่น่าจะเรียกตัวเอง)
ดังนั้นสิ่งที่ล้มเหลว
sh /home/incero/startup_script.sh
ล้มเหลว เกือบจะแน่นอน
/script.sh
เรารู้ว่ามันวิ่งเพราะมันดาวน์โหลด
(ไม่เช่นนั้นจะเป็นสิ่งสำคัญที่จะตรวจสอบให้แน่ใจว่ามันทำงานในกรณีที่/bin
ไม่ได้อยู่ในPATH - rc.local
ไม่จำเป็นต้องเหมือนกับPATH
เมื่อคุณลงชื่อเข้าใช้หาก/bin
ไม่ได้อยู่ในrc.local
เส้นทางของสิ่งนี้ จะต้องsh
มีการเรียกใช้เป็น/bin/sh
เพราะมันทำงาน/bin
อยู่ในPATH
ซึ่งหมายความว่าคุณสามารถเรียกใช้คำสั่งอื่น ๆ ที่อยู่ใน/bin
โดยไม่ต้องมีคุณสมบัติครบถ้วนชื่อตัวอย่างเช่นคุณสามารถเรียกใช้เพียงแค่chmod
มากกว่า/bin/chmod
อย่างไรก็ตามในการรักษาสไตล์ของคุณ ในrc.local
ฉันใช้ชื่อที่ผ่านการรับรองสำหรับคำสั่งทั้งหมดยกเว้นsh
เมื่อใดก็ตามที่ฉันแนะนำให้คุณเรียกใช้พวกเขา)
เราค่อนข้างแน่ใจว่า/bin/chmod +x /script.sh
ไม่เคยวิ่ง (หรือคุณจะเห็นว่า/script.sh
ถูกประหารชีวิต) และเรารู้sh /script.sh
ว่าไม่ได้ทำงานเช่นกัน
/script.sh
แต่มันดาวน์โหลด มันประสบความสำเร็จ! มันจะล้มเหลวได้อย่างไร?
สองความหมายของความสำเร็จ
มีสองสิ่งที่แตกต่างกันที่บุคคลอาจหมายถึงเมื่อเขา / เธอพูดว่าคำสั่งประสบความสำเร็จ:
- มันทำในสิ่งที่คุณต้องการให้ทำ
- มันรายงานว่ามันประสบความสำเร็จ
และเพื่อความล้มเหลว เมื่อบุคคลแจ้งว่าคำสั่งล้มเหลวอาจหมายถึง:
- มันไม่ได้ทำในสิ่งที่คุณต้องการให้ทำ
- มันรายงานว่ามันล้มเหลว
วิ่งสคริปต์ด้วยsh -e
เช่นrc.local
จะหยุดการทำงานครั้งแรกที่คำสั่งรายงานว่ามันล้มเหลว มันไม่ได้สร้างความแตกต่างในสิ่งที่คำสั่งทำจริง
ถ้าคุณตั้งใจที่จะล้มเหลวรายงานเมื่อมันไม่สิ่งที่คุณต้องการนี้เป็นข้อผิดพลาดในstartup_script.sh
startup_script.sh
- ข้อบกพร่องบางอย่างทำให้สคริปต์ไม่สามารถทำสิ่งที่คุณต้องการได้ พวกเขาส่งผลกระทบต่อสิ่งที่โปรแกรมเมอร์เรียกผลข้างเคียงของมัน
- และข้อบกพร่องบางอย่างป้องกันสคริปต์จากการรายงานอย่างถูกต้องหรือไม่มันประสบความสำเร็จ พวกเขาส่งผลกระทบต่อสิ่งที่โปรแกรมเมอร์เรียกค่าตอบแทนของมัน(ซึ่งในกรณีนี้คือสถานะทางออก )
มีแนวโน้มมากที่สุดที่startup_script.sh
ทำทุกสิ่งที่ควรยกเว้นรายงานว่าล้มเหลว
วิธีรายงานความสำเร็จหรือล้มเหลว
สคริปต์คือรายการคำสั่งเป็นศูนย์หรือมากกว่า แต่ละคำสั่งมีสถานะการออก สมมติว่าไม่มีความล้มเหลวในการรันสคริปต์จริง (ตัวอย่างเช่นหากล่ามไม่สามารถอ่านบรรทัดถัดไปของสคริปต์ขณะที่เรียกใช้) สถานะการออกของสคริปต์คือ:
0
(สำเร็จ) หากสคริปต์ว่างเปล่า (กล่าวคือไม่มีคำสั่ง)
N
หากสคริปต์จบลงด้วยผลลัพธ์ของคำสั่งโดยที่บางรหัสทางออกexit N
N
- โค้ดทางออกของคำสั่งสุดท้ายที่รันในสคริปต์มิฉะนั้น
เมื่อรันโปรแกรมที่รันได้มันจะรายงานโค้ดออกของตัวเอง - มันไม่ได้มีไว้สำหรับสคริปต์เท่านั้น (และในทางเทคนิคแล้วรหัสการออกจากสคริปต์คือรหัสการออกที่ส่งคืนโดยเชลล์ที่รัน)
ตัวอย่างเช่นหากโปรแกรม C ลงท้ายด้วยexit(0);
หรือreturn 0;
ในmain()
ฟังก์ชั่นของมันรหัส0
จะถูกกำหนดให้กับระบบปฏิบัติการซึ่งจะให้กระบวนการเรียก (ซึ่งอาจเป็นเชลล์ที่โปรแกรมทำงาน)
0
หมายถึงโปรแกรมที่ประสบความสำเร็จ หมายเลขอื่น ๆ ทุกหมายความว่ามันล้มเหลว (ด้วยวิธีนี้ตัวเลขที่แตกต่างกันบางครั้งสามารถอ้างถึงสาเหตุต่าง ๆ ที่โปรแกรมล้มเหลว)
คำสั่งหมายถึงการล้มเหลว
บางครั้งคุณรันโปรแกรมด้วยความตั้งใจว่าจะล้มเหลว ในสถานการณ์เหล่านี้คุณอาจคิดว่าความล้มเหลวเป็นความสำเร็จแม้ว่าจะไม่ใช่ข้อผิดพลาดที่โปรแกรมรายงานความล้มเหลว ตัวอย่างเช่นคุณอาจใช้rm
ไฟล์ที่คุณสงสัยว่าไม่มีอยู่จริงเพื่อให้แน่ใจว่าไฟล์นั้นถูกลบไปแล้ว
สิ่งนี้อาจเกิดขึ้นstartup_script.sh
ก่อนที่จะหยุดทำงาน คำสั่งสุดท้ายที่จะทำงานในสคริปต์อาจจะมีการรายงานความล้มเหลว (แม้ว่า "ความล้มเหลว" มันอาจจะโดยสิ้นเชิงปรับหรือจำเป็นต้องได้) ซึ่งจะทำให้เกิดความล้มเหลวรายงานสคริปต์
การทดสอบหมายถึงการล้มเหลว
คำสั่งพิเศษชนิดหนึ่งคือการทดสอบโดยที่ฉันหมายถึงการรันคำสั่งสำหรับค่าส่งคืนแทนที่จะเป็นผลข้างเคียง นั่นคือการทดสอบคือคำสั่งที่ทำงานเพื่อให้สามารถตรวจสอบสถานะการออก (และดำเนินการตาม)
ตัวอย่างเช่นสมมติว่าฉันลืมว่า 4 เท่ากับ 5 โชคดีฉันรู้การเขียนสคริปต์เชลล์:
if [ 4 -eq 5 ]; then
echo "Yeah, they're totally the same."
fi
ที่นี่การทดสอบ[ -eq 5 ]
ล้มเหลวเพราะปรากฎ 4 ≠ 5 หลังจากทั้งหมด ไม่ได้หมายความว่าการทดสอบทำงานไม่ถูกต้อง มันทำ. มีหน้าที่ตรวจสอบว่า 4 = 5 จากนั้นรายงานความสำเร็จหากเป็นเช่นนั้นและล้มเหลวหากไม่ได้
ที่คุณเห็นในสคริปต์เปลือกความสำเร็จยังสามารถหมายถึงความจริงและความล้มเหลวยังสามารถหมายถึงเท็จ
แม้ว่าecho
คำสั่งจะไม่ทำงาน แต่if
บล็อกโดยรวมจะกลับมาประสบความสำเร็จได้
อย่างไรก็ตามฉันควรเขียนให้สั้นกว่านี้:
[ 4 -eq 5 ] && echo "Yeah, they're totally the same."
นี่เป็นชวเลขทั่วไป &&
เป็นบูลีน และโอเปอเรเตอร์ &&
แสดงออกซึ่งประกอบด้วย&&
งบทั้งสองข้างกลับเท็จ (ล้มเหลว) เว้นแต่ทั้งสองฝ่ายกลับจริง (ความสำเร็จ) เช่นเดียวกับปกติและ
ถ้ามีคนถามคุณว่า "ดีเร็กไปที่ห้างสรรพสินค้าแล้วคิดเรื่องผีเสื้อเหรอ?" และคุณรู้ว่าดีเร็กไม่ได้ไปที่ห้างสรรพสินค้าคุณไม่ต้องคิดมากถ้าเขานึกถึงผีเสื้อ
ในทำนองเดียวกันถ้าคำสั่งทางด้านซ้ายของ&&
ล้มเหลว (เท็จ) การ&&
แสดงออกทั้งหมดล้มเหลวทันที (เท็จ) คำสั่งทางด้านขวาของ&&
จะไม่ทำงาน
ที่นี่[ 4 -eq 5 ]
วิ่ง มัน "ล้มเหลว" (คืนค่าเท็จ) ดังนั้นการ&&
แสดงออกทั้งหมดล้มเหลว echo "Yeah, they're totally the same."
ไม่เคยวิ่ง ทุกอย่างทำงานตามที่ควรจะเป็น แต่คำสั่งนี้รายงานความล้มเหลว (แม้ว่าเงื่อนไขอื่น ๆ ที่เทียบเท่าif
เหนือรายงานสำเร็จ)
หากพบว่าเป็นคำสั่งสุดท้ายในสคริปต์ (และสคริปต์ที่ได้มันมากกว่าการยกเลิกในบางจุดก่อนที่จะ) สคริปต์ทั้งหมดจะรายงานความล้มเหลว
มีการทดสอบมากมายนอกเหนือจากนี้ ตัวอย่างเช่นมีการทดสอบด้วย||
("หรือ") อย่างไรก็ตามตัวอย่างข้างต้นควรเพียงพอที่จะอธิบายว่าการทดสอบคืออะไรและทำให้คุณสามารถใช้เอกสารประกอบได้อย่างมีประสิทธิภาพเพื่อพิจารณาว่าคำสั่ง / คำสั่งเฉพาะเป็นการทดสอบ
sh
เทียบกับsh -e
Revisited
ตั้งแต่สาย (เห็นคำถามนี้ ) ที่ด้านบนของที่มีระบบปฏิบัติการเรียกใช้สคริปต์ราวกับว่ามันถูกเรียกด้วยคำสั่ง:#!
/etc/rc.local
sh -e
sh -e /etc/rc.local
ในทางตรงกันข้ามสคริปต์อื่น ๆ ของคุณเช่นstartup_script.sh
ทำงานโดยไม่มีการ-e
ตั้งค่าสถานะ:
sh /home/incero/startup_script.sh
ดังนั้นพวกเขายังคงทำงานแม้ว่าคำสั่งในรายงานความล้มเหลว
นี่เป็นเรื่องปกติและดี rc.local
ควรเรียกใช้sh -e
และสคริปต์อื่น ๆ ส่วนใหญ่ - รวมถึงสคริปต์ส่วนใหญ่ที่ดำเนินการโดย - rc.local
ไม่ควร
เพียงให้แน่ใจว่าได้จดจำความแตกต่าง:
สคริปต์ทำงานด้วยsh -e
ความล้มเหลวในการออกจากการรายงานในครั้งแรกที่คำสั่งนั้นออกจากการรายงานความล้มเหลว
ราวกับว่าสคริปต์เป็นคำสั่งยาว ๆ เดียวซึ่งประกอบด้วยคำสั่งทั้งหมดในสคริปต์ที่เข้าร่วมกับ&&
โอเปอเรเตอร์
สคริปต์ทำงานด้วยsh
(ไม่-e
) ทำงานต่อไปจนกว่าพวกเขาจะได้รับคำสั่งที่ยกเลิก (ออกจาก) หรือสิ้นสุดสคริปต์ ความสำเร็จหรือความล้มเหลวของทุกคำสั่งนั้นไม่เกี่ยวข้องกันเป็นหลัก (เว้นแต่ว่าคำสั่งถัดไปจะตรวจสอบ) สคริปต์ออกจากสถานะทางออกของการรันคำสั่งล่าสุด
ช่วยให้สคริปต์ของคุณเข้าใจว่าไม่ใช่ความล้มเหลว
คุณจะป้องกันไม่ให้สคริปต์ของคุณคิดว่าสคริปต์ล้มเหลวได้อย่างไร
คุณดูว่าเกิดอะไรขึ้นก่อนที่มันจะทำงานเสร็จ
หากคำสั่งล้มเหลวเมื่อมันควรจะประสบความสำเร็จให้คิดออกว่าทำไมและแก้ไขปัญหา
หากคำสั่งล้มเหลวและนั่นคือสิ่งที่ถูกต้องที่จะเกิดขึ้นให้ป้องกันสถานะความล้มเหลวนั้นจากการเผยแพร่
วิธีหนึ่งในการป้องกันสถานะความล้มเหลวจากการเผยแพร่คือการเรียกใช้คำสั่งอื่นที่ประสบความสำเร็จ /bin/true
ไม่มีผลข้างเคียงและรายงานความสำเร็จ (เช่นเดียวกับที่/bin/false
ทำอะไรและล้มเหลวด้วย)
exit 0
อีกประการหนึ่งคือเพื่อให้แน่ใจว่าสคริปต์ที่ถูกยกเลิกโดย
นั่นไม่จำเป็นต้องเป็นสิ่งเดียวexit 0
กับตอนท้ายของสคริปต์ ตัวอย่างเช่นอาจมีif
-block ที่สคริปต์ออกจากภายใน
เป็นการดีที่สุดที่จะรู้ว่าสิ่งใดที่ทำให้สคริปต์ของคุณรายงานความล้มเหลวก่อนที่จะรายงานความสำเร็จ ถ้ามันล้มเหลวอย่างใดอย่างหนึ่ง (ในแง่ของการไม่ทำสิ่งที่คุณต้องการให้ทำ) คุณไม่ต้องการให้รายงานความสำเร็จ
การแก้ไขด่วน
หากคุณไม่สามารถstartup_script.sh
ประสบความสำเร็จในการออกจากการรายงานคุณสามารถเปลี่ยนคำสั่งในการrc.local
ดำเนินการเพื่อให้คำสั่งนั้นรายงานความสำเร็จแม้ว่าจะstartup_script.sh
ไม่ได้
ขณะนี้คุณมี:
sh /home/incero/startup_script.sh
คำสั่งนี้มีผลข้างเคียงที่เหมือนกัน (เช่นผลข้างเคียงของการทำงานstartup_script.sh
) แต่รายงานความสำเร็จเสมอ:
sh /home/incero/startup_script.sh || /bin/true
จำไว้ว่าดีกว่าที่จะทราบว่าเหตุใดจึงstartup_script.sh
รายงานความล้มเหลวและแก้ไข
Quick Fix ทำงานอย่างไร
นี่เป็นตัวอย่างของการ||
ทดสอบหรือการทดสอบ
สมมติว่าคุณถามว่าฉันเอาขยะออกไปหรือแปรงนกฮูก ถ้าฉันนำถังขยะออกมาฉันสามารถพูดได้ว่า "ใช่" ตามจริงแม้ว่าฉันจะจำไม่ได้หรือไม่ว่าฉันแปรงนกฮูก
คำสั่งทางด้านซ้ายของการ||
รัน ถ้ามันประสบความสำเร็จ (จริง) จากนั้นทางด้านขวามือไม่จำเป็นต้องวิ่ง ดังนั้นหากstartup_script.sh
รายงานความสำเร็จtrue
คำสั่งจะไม่ทำงาน
อย่างไรก็ตามหากstartup_script.sh
รายงานความล้มเหลว[ฉันไม่ได้นำถังขยะออก]ดังนั้นผลลัพธ์ของ/bin/true
[ถ้าฉันแปรงนกฮูก] นั้นสำคัญ
/bin/true
ส่งคืนความสำเร็จเสมอ (หรือจริงบางครั้งเราเรียกมันว่า) ดังนั้นคำสั่งทั้งหมดจะสำเร็จและคำสั่งถัดไปrc.local
สามารถเรียกใช้
หมายเหตุเพิ่มเติมเกี่ยวกับความสำเร็จ / ความล้มเหลวจริง / เท็จศูนย์ / ไม่ใช่ศูนย์
อย่าลังเลที่จะเพิกเฉยต่อสิ่งนี้ คุณอาจต้องการอ่านสิ่งนี้หากคุณเขียนโปรแกรมในภาษามากกว่าหนึ่งภาษา (เช่นไม่ใช่แค่เชลล์สคริปต์)
มันเป็นจุดที่สับสนอย่างมากสำหรับเชลล์สคริปเตอร์ที่ใช้ภาษาโปรแกรมเช่น C และสำหรับโปรแกรมเมอร์ C ที่ใช้เชลล์สคริปเพื่อค้นพบ:
ในการเขียนสคริปต์เชลล์:
- ค่าการกลับมาของ
0
วิธีการที่ประสบความสำเร็จและ / หรือความจริง
- ค่าการกลับมาของสิ่งอื่นที่ไม่ใช่
0
หมายถึงความล้มเหลวและ / หรือเท็จ
ในการเขียนโปรแกรม C:
- ค่าส่งคืน
0
หมายความว่าเป็นเท็จ ..
- ค่าการกลับมาของสิ่งอื่นที่ไม่ใช่
0
วิธีการที่แท้จริง
- ไม่มีกฎง่ายๆสำหรับสิ่งที่หมายถึงความสำเร็จและสิ่งที่หมายถึงความล้มเหลว บางครั้ง
0
หมายถึงความสำเร็จบางครั้งก็หมายถึงความล้มเหลวในบางครั้งก็หมายความว่าผลรวมของตัวเลขทั้งสองที่คุณเพิ่งเพิ่มนั้นเป็นศูนย์ ค่าส่งคืนในการเขียนโปรแกรมทั่วไปใช้เพื่อส่งสัญญาณข้อมูลหลากหลายประเภท
- สถานะการออกเป็นตัวเลขของโปรแกรมควรระบุว่าสำเร็จหรือล้มเหลวตามกฎสำหรับการสร้างสคริปต์เชลล์ นั่นคือแม้ว่าจะ
0
หมายถึงเท็จในโปรแกรม C ของคุณคุณยังคงทำให้โปรแกรมของคุณกลับมา0
เป็นรหัสออกหากคุณต้องการให้มันรายงานว่ามันประสบความสำเร็จ (ซึ่งเชลล์แล้วตีความว่าเป็นจริง )