ฉันจะเขียนเชลล์สคริปต์ที่ออกได้อย่างไรหากส่วนหนึ่งล้มเหลว? ตัวอย่างเช่นหากข้อมูลโค้ดต่อไปนี้ล้มเหลวสคริปต์ควรออก
n=0
until [ $n -ge 5 ]
do
gksu *command* && break
n=$[$n+1]
sleep 3
ฉันจะเขียนเชลล์สคริปต์ที่ออกได้อย่างไรหากส่วนหนึ่งล้มเหลว? ตัวอย่างเช่นหากข้อมูลโค้ดต่อไปนี้ล้มเหลวสคริปต์ควรออก
n=0
until [ $n -ge 5 ]
do
gksu *command* && break
n=$[$n+1]
sleep 3
คำตอบ:
วิธีหนึ่งที่จะเพิ่มset -e
ไปยังจุดเริ่มต้นของสคริปต์ของคุณ นั่นหมายถึง (จากhelp set
):
-e Exit immediately if a command exits with a non-zero status.
ดังนั้นหากคำสั่งใด ๆ ของคุณล้มเหลวสคริปต์จะจบการทำงาน
หรือคุณสามารถเพิ่มexit
ข้อความชี้แจงที่จุดล้มเหลวที่เป็นไปได้:
command || exit 1
set -e
เป็นวิธีเดียวที่ฉันรู้ที่จะทำ
set -e
เป็นsleep
( break
เป็น builtin พิเศษจะทำให้เกิดสคริปต์เพื่อออกจากความล้มเหลวในเปลือกหอยมากที่สุดคำสั่งในif
หรือด้านซ้ายของ&&
ยังไม่ได้รับผลกระทบจากset -e
, n=...
อาจล้มเหลวถ้าn
เป็นแบบอ่านอย่างเดียว แต่แล้ว ที่จะออกจากสคริปต์โดยไม่ใช้set -e
) ดังนั้นการตีความจึงฟังดูไม่น่าจะเป็นไปได้ ฉันเห็นด้วยกับคำถามที่พูดไม่ดี
คุณสามารถออกจากสคริปต์ได้ทุกที่โดยใช้คำexit
สำคัญ นอกจากนี้คุณยังสามารถระบุรหัสออกเพื่อบ่งบอกถึงโปรแกรมอื่น ๆ ที่หรือวิธีการที่สคริปต์ของคุณล้มเหลวเช่นexit 1
หรือexit 2
อื่น ๆ (โดยการประชุมรหัสออก 0 สำหรับความสำเร็จและสิ่งที่มากกว่า 0 หมายถึงความล้มเหลวอย่างไรก็ตามโดยการประชุมออก รหัสข้างต้น 127 สงวนไว้สำหรับการยุติที่ผิดปกติ (เช่นโดยสัญญาณ)
การก่อสร้างทั่วไปเพื่อออกจากความล้มเหลวคือ
if [ failure condition ]; then
exit n
fi
ที่มีความเหมาะสมและfailure condition
n
แต่ในบางสถานการณ์คุณอาจดำเนินการแตกต่างกัน ทีนี้สำหรับกรณีของคุณฉันตีความคำถามของคุณว่าหากการเรียกร้องข้อใดข้อหนึ่งในห้าข้อgksu
ล้มเหลวคุณจะต้องออก วิธีหนึ่งคือการใช้ฟังก์ชั่นเช่นนี้
function try_command {
for i in 1 2 3 4 5 ; do
if gksu command ; then
return 0
fi
fi
exit 1
}
try_command
แล้วเรียกห่วงโดย
มีวิธีการตอบคำถามของคุณขั้นสูงหรือซับซ้อน อย่างไรก็ตามวิธีการแก้ปัญหาข้างต้นนั้นเข้าถึงได้ง่ายสำหรับผู้เริ่มต้นมากกว่าพูดว่าโซลูชันของ Stephane
attempt=0
until gksu command; do
attempt=$((attempt + 1))
if [ "$attempt" -gt 5 ]; then
exit 1
fi
done
exit
ออกจากสคริปต์ยกเว้นว่ามันจะถูกเรียกใน subshell หากส่วนหนึ่งของสคริปต์นั้นอยู่ใน subshell เช่นเนื่องจากอยู่ใน(...)
หรือ$(...)
หรือเป็นส่วนหนึ่งของไปป์ไลน์แล้วมันจะออกจากsubshellนั้นเท่านั้น
ในกรณีดังกล่าวหากคุณต้องการให้สคริปต์ออกจากส่วนย่อยคุณจะต้องเรียกexit
ใช้ส่วนย่อยนั้นออก
ตัวอย่างเช่นที่นี่มี 2 ระดับย่อยของ subshells:
(
life=hard
output=$(
echo blah
[ "$life" = easy ] || exit 1 # exit subshell
echo blih not run
) || exit # if the subshell exits with a non-zero exit status,
# exit as well with the same exit status
echo not run either
) || exit # if the subshell exits with a non-zero exit status,
# exit as well with the same exit status
มันอาจกลายเป็นเรื่องยากหาก subshell เป็นส่วนหนึ่งของไปป์ไลน์ bash
มี$PIPESTATUS
อาเรย์พิเศษคล้ายกับzsh
ของ$pipestatus
ที่สามารถช่วยคุณได้ที่นี่:
{
echo foo
exit 1
echo bar
} | wc -c
subshell_ret=${PIPESTATUS[0]}
if [ "$subshell_ret" -ne 0 ]; then
exit "$subshell_ret"
fi
กับดักจะดำเนินการเมื่อได้รับสัญญาณ
trap "echo EXIT; exit" 0
trap "echo HUP; exit" 1
trap "echo CTL-C; exit" 2
trap "echo QUIT; exit" 3
trap "echo ERR; exit" ERR
n=0
until [ $n -ge 5 ]
do
n=$[$n+1]
echo $n
sleep 3
done
เรียกใช้สิ่งนี้และปล่อยให้มันออกตามปกติ วางกับสัญญาณ 0
EXIT
เรียกใช้อีกครั้งและขัดจังหวะด้วย ^ C มันดักทั้งสัญญาณ 2 และสัญญาณ 0
CTL-C
EXIT
สถานะการออกที่ไม่เป็นศูนย์จะดักบน ERR
ERR
EXIT
set -e
คุณลักษณะ มันใช้ไม่ได้จริงที่นี่ OP ต้องการออกจากสคริปต์หลังจาก 5 ความพยายามที่ล้มเหลวในการเรียกใช้คำสั่ง