ฉันเป็น noob ในการเขียนสคริปต์เชลล์ ฉันต้องการพิมพ์ข้อความและออกจากสคริปต์หากคำสั่งล้มเหลว ฉันพยายามแล้ว:
my_command && (echo 'my_command failed; exit)
แต่มันไม่ทำงาน มันยังคงดำเนินการตามคำแนะนำต่อไปนี้บรรทัดในสคริปต์ ฉันใช้ Ubuntu และทุบตี
ฉันเป็น noob ในการเขียนสคริปต์เชลล์ ฉันต้องการพิมพ์ข้อความและออกจากสคริปต์หากคำสั่งล้มเหลว ฉันพยายามแล้ว:
my_command && (echo 'my_command failed; exit)
แต่มันไม่ทำงาน มันยังคงดำเนินการตามคำแนะนำต่อไปนี้บรรทัดในสคริปต์ ฉันใช้ Ubuntu และทุบตี
คำตอบ:
ลอง:
my_command || { echo 'my_command failed' ; exit 1; }
การเปลี่ยนแปลงที่สี่:
&&
เป็น||
{ }
แทน( )
;
หลังจากexit
และ{
และก่อน}
เนื่องจากคุณต้องการพิมพ์ข้อความและออกคำสั่งเฉพาะเมื่อล้มเหลว (ทางออกที่มีค่าที่ไม่ใช่ศูนย์) ที่คุณต้องการไม่ได้||
&&
cmd1 && cmd2
จะทำงานcmd2
เมื่อcmd1
สำเร็จ (ค่าทางออก0
) อยู่ที่ไหน
cmd1 || cmd2
จะทำงานcmd2
เมื่อcmd1
ล้มเหลว (ค่าออกไม่ใช่ศูนย์)
การใช้( )
ทำให้คำสั่งที่อยู่ข้างในนั้นทำงานในsub-shellและการเรียก a exit
จากนั้นทำให้คุณออกจาก sub-shell และไม่ใช่เชลล์เดิมของคุณดังนั้นการดำเนินการต่อในเชลล์เดิมของคุณ
เพื่อเอาชนะการใช้งานนี้ { }
ต้องการการเปลี่ยนแปลงสองครั้งล่าสุดโดย bash
{ (>&2 echo 'my_command failed') ; exit 1; }
คำตอบอื่น ๆ ได้ครอบคลุมคำถามโดยตรงดี set -e
แต่คุณอาจจะสนใจในการใช้ ด้วยสิ่งนั้นคำสั่งใด ๆ ที่ล้มเหลว (นอกบริบทที่เฉพาะเจาะจงเช่นif
การทดสอบ) จะทำให้สคริปต์ยกเลิก สำหรับบางสคริปต์มันมีประโยชน์มาก
set -e
มีกฎที่ยาวและลึกลับเกี่ยวกับเวลาที่ใช้งานและเมื่อไม่มี (หากใครก็ตามทำงานif yourfunction; then ...
แล้วset -e
จะไม่เริ่มทำงานภายในyourfunction
หรือสิ่งที่เรียกเพราะรหัสนั้นถูกพิจารณาว่าเป็น "ตรวจสอบ") ดูในส่วนของแบบฝึกหัดของ BashFAQ # 105พูดคุยเรื่องนี้และข้อผิดพลาดอื่น ๆ (บางส่วนใช้เฉพาะกับรุ่นเปลือกเฉพาะเท่านั้นดังนั้นคุณต้องแน่ใจว่าได้ทดสอบกับทุกรุ่นที่อาจใช้รันสคริปต์ของคุณ)
โปรดทราบว่าสถานะทางออกของแต่ละคำสั่งจะถูกเก็บไว้ในตัวแปรเชลล์ $? ซึ่งคุณสามารถตรวจสอบได้ทันทีหลังจากเรียกใช้คำสั่ง สถานะที่ไม่เป็นศูนย์แสดงถึงความล้มเหลว:
my_command
if [ $? -eq 0 ]
then
echo "it worked"
else
echo "it failed"
fi
echo "Just finished step A"
โดยไม่ทราบว่าการecho
เขียนทับสิ่ง$?
ที่กำลังจะถูกตรวจสอบในภายหลัง
หากคุณต้องการพฤติกรรมนั้นสำหรับคำสั่งทั้งหมดในสคริปต์ของคุณเพียงเพิ่ม
set -e
set -o pipefail
ที่จุดเริ่มต้นของสคริปต์ ตัวเลือกคู่นี้บอกให้ล่ามทุบตีเพื่อออกเมื่อใดก็ตามที่คำสั่งกลับมาพร้อมกับรหัสออกไม่เป็นศูนย์
สิ่งนี้ไม่อนุญาตให้คุณพิมพ์ข้อความออก
trap
bash ในตัว
set -o pipefail
อาจไม่ใช่พฤติกรรมที่ต้องการ ยังคงขอบคุณที่ชี้ให้เห็น!
set -e
ไม่น่าเชื่อถือสอดคล้องหรือคาดการณ์ได้ทั้งหมด! เพื่อโน้มน้าวตัวเองจากการที่ตรวจสอบส่วนการออกกำลังกายของBashFAQ # 105หรือตารางเปรียบเทียบพฤติกรรมเปลือกหอยที่แตกต่างกันที่in-ulm.de/~mascheck/various/set-e
ฉันแฮ็กอัพสำนวนต่อไปนี้:
echo "Generating from IDL..."
idlj -fclient -td java/src echo.idl
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi
echo "Compiling classes..."
javac *java
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi
echo "Done."
นำหน้าแต่ละคำสั่งด้วย echo ที่ให้ข้อมูลและทำตามแต่ละคำสั่งด้วย
if [ $? -ne 0 ];...
บรรทัดเดียวกัน (แน่นอนคุณสามารถแก้ไขข้อความแสดงข้อผิดพลาดได้หากต้องการ)
if ! javac *.java; then ...
- ทำไมต้องกังวลด้วย$?
เลย?
การให้บริการmy_command
ได้รับการออกแบบตามมาตรฐานของแคนนอนคือคืน 0 เมื่อสำเร็จแล้ว&&
ตรงข้ามกับสิ่งที่คุณต้องการ ||
คุณต้องการ
โปรดทราบด้วย(
ว่าไม่ได้ดูเหมือนจะถูกต้องสำหรับฉันในการทุบตี แต่ฉันไม่สามารถลองจากที่ฉันอยู่ บอกฉัน.
my_command || {
echo 'my_command failed' ;
exit 1;
}
คุณยังสามารถใช้หากคุณต้องการรักษาสถานะข้อผิดพลาดในการออกและมีไฟล์ที่สามารถอ่านได้ด้วยหนึ่งคำสั่งต่อบรรทัด:
my_command1 || exit $?
my_command2 || exit $?
อย่างไรก็ตามสิ่งนี้จะไม่พิมพ์ข้อความแสดงข้อผิดพลาดเพิ่มเติม แต่ในบางกรณีข้อผิดพลาดจะถูกพิมพ์โดยคำสั่งที่ล้มเหลวอยู่แล้ว
exit $?
; เพียงexit
ใช้$?
เป็นค่าเริ่มต้น
trap
builtin เปลือกช่วยให้สัญญาณจับการและเงื่อนไขที่มีประโยชน์อื่น ๆ รวมทั้งการดำเนินการคำสั่งล้มเหลว (เช่นผลตอบแทนสถานะที่ไม่ใช่ศูนย์) ดังนั้นหากคุณไม่ต้องการทดสอบสถานะการส่งคืนของทุกคำสั่งเดียวอย่างชัดเจนคุณสามารถพูดได้trap "your shell code" ERR
และรหัสเชลล์จะถูกดำเนินการเมื่อใดก็ตามที่คำสั่งส่งคืนสถานะที่ไม่เป็นศูนย์ ตัวอย่างเช่น:
trap "echo script failed; exit 1" ERR
โปรดทราบว่าเช่นเดียวกับกรณีอื่น ๆ ที่จับคำสั่งที่ล้มเหลวท่อจำเป็นต้องได้รับการดูแลเป็นพิเศษ false | true
เจตจำนงดังกล่าวข้างต้นไม่ได้จับ