ฉันจะเขียนเชลล์สคริปต์ที่ออกได้อย่างไรหากส่วนหนึ่งล้มเหลว? ตัวอย่างเช่นหากข้อมูลโค้ดต่อไปนี้ล้มเหลวสคริปต์ควรออก
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 1set -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 ความพยายามที่ล้มเหลวในการเรียกใช้คำสั่ง