วิธีปิดการใช้งาน set -e สำหรับแต่ละคำสั่ง?


36

คำสั่ง set -e ทำให้สคริปต์ bash ล้มเหลวทันทีเมื่อคำสั่งใด ๆ ส่งคืนโค้ดออกที่ไม่ใช่ศูนย์

  1. มีวิธีที่ง่ายและสง่างามในการปิดการทำงานนี้สำหรับคำสั่งแต่ละคำสั่งภายในสคริปต์หรือไม่?

  2. ฟังก์ชั่นนี้มีการบันทึกไว้ที่ไหนในคู่มืออ้างอิง Bash ( http://www.gnu.org/software/bash/manual/bashref.html )

คำตอบ:


29
  1. บางสิ่งเช่นนี้

    #!/usr/bin/env bash
    
    set -e
    echo hi
    
    # disable exitting on error temporarily
    set +e
    aoeuidhtn
    echo next line
    
    # bring it back
    set -e
    ao
    
    echo next line

    วิ่ง:

    $ ./test.sh
    hi
    ./test.sh: line 7: aoeuidhtn: command not found
    next line
    ./test.sh: line 11: ao: command not found
  2. มันอธิบายไว้ในsetตัวช่วย:

    $ type set
    set is a shell builtin
    $ help set
    (...)
    Using + rather than - causes these flags to be turned off.

เป็นเดียวกันเอกสารที่นี่: https://www.gnu.org/software/bash/manual/bashref.html#The-Set-Builtin


ขอบคุณ! ฉันพบความเป็นไปได้อื่น: #! / bin / bash set -e # Uncomment บรรทัดถัดไปเพื่อดู set -e effect: #blubb if blubb; จากนั้นเสียงก้อง "สั่งบลับประสบความสำเร็จ" อย่างอื่นสะท้อน "คำสั่งบัพบล้มเหลวรหัสออก: $?" fi echo สคริปต์ปกติออก
กุสตาฟ

22

ทางเลือกในการยกเลิกการประกันตัวผิดพลาดคือการบังคับให้ประสบความสำเร็จไม่ว่าจะเกิดอะไรขึ้น คุณสามารถทำสิ่งนี้:

cmd_to_run || true

นั่นจะส่งคืน 0 (จริง) ดังนั้นชุด -e ไม่ควรถูกเรียก


3
faulty_cmd || :เป็นอีกหนึ่งสำนวนที่เป็นที่นิยมสำหรับเรื่องนี้ ( :เป็นคำสั่งตรงกันtrue)
ulidtko

3
@ulidtko - น่าสนใจ พาฉันลงหลุมกระต่ายเพื่อค้นหาstackoverflow.com/questions/3224878/นี้เพื่อรับประวัติศาสตร์เกี่ยวกับ true vs. :
ernie

12

หากคุณพยายามจับรหัสส่งคืน / ข้อผิดพลาด (ฟังก์ชันหรือทางแยก) สิ่งนี้จะทำงาน:

function xyz {
    return 2
}

xyz && RC=$? || RC=$?

8

หากตัวเลือก "exit ทันทีเปลือก" ใช้หรือถูกละเว้นขึ้นอยู่กับบริบทของคำสั่งดำเนินการ (ดูคู่มือ Bash Reference Manual ใน Set Builtin - ขอบคุณ Arkadiusz Drabczyk)

โดยเฉพาะอย่างยิ่งตัวเลือกจะถูกละเว้นถ้าคำสั่งเป็นส่วนหนึ่งของการทดสอบในคำสั่ง if ดังนั้นจึงเป็นไปได้ที่จะดำเนินการคำสั่งและตรวจสอบความสำเร็จหรือความล้มเหลวภายใน "exit ทันทีบริบท" โดยใช้คำสั่ง if เช่นนี้:

#!/bin/bash

set -e

# Uncomment next line to see set -e effect:
#blubb

if blubb; then
  echo "Command blubb was succesful."
else 
  echo "Command blubb failed. Exit code: $?"
fi
echo "Script exited normally."

เป็นไปได้ที่จะละเว้นคำสั่ง "แล้ว" และใช้บรรทัดน้อยลง:

if blubb; then :;
else echo "Command blubb failed. Exit code: $?"; fi

2

วิธีการอื่นซึ่งฉันพบว่าค่อนข้างตรงไปตรงมา (และใช้กับsetตัวเลือกอื่นนอกเหนือจาก-e):

ใช้ประโยชน์จาก$-เพื่อคืนค่าการตั้งค่า

ตัวอย่างเช่น:

oldopt=$-
set +e
# now '-e' is definitely disabled.
# do some stuff...

# Restore things back to how they were
set -$oldopt

แม้ว่า-eโดยเฉพาะอย่างยิ่งตัวเลือกอื่น ๆ ได้กล่าวถึง ( || trueหรือ "ใส่ในif") อาจจะเป็นสำนวนมากขึ้น


0

จริง ๆ แล้วฉันมีคำถามที่คล้ายกันเมื่อเร็ว ๆ นี้ (แม้ว่าฉันจะไม่ได้โพสต์ แต่ฉันได้ไปถึงมัน) และจากสิ่งที่ฉันเห็นมันดูเหมือนว่าจะใช้ set + e ก่อนคำสั่งและ set -e ทำงานได้อย่างหรูหราที่สุด นี่คือตัวอย่างการจับการตอบสนองของคำสั่งและไม่ปล่อยให้ข้อผิดพลาดทิ้งไป

#!/bin/sh

args=""
for argcol in $*
do
    args="${args} ${argcol}"
done
fortunevar=""
fortfail=""
{
    set +e
    fortunevar=`fortune $args`
    fortfail=$?
    set -e
} &> /dev/null
if [ $fortfail == 0 ]
then
    echo ${fortunevar}
    say ${fortunevar}
else
    echo misfortune: an illegal option was detected!
    echo misfortune: usage: misfortune [-afilosw] [-m pattern][ [#%] file/directory/all]
fi

สิ่งนี้จะจับเอาท์พุทของ 'ฟอร์จูน' การตรวจสอบสถานะทางออกและเสียงสะท้อนและบอกว่ามัน ฉันคิดว่านี่คือสิ่งที่คุณขอหรืออย่างน้อยก็คล้ายกัน? อย่างไรก็ตามหวังว่านี่จะช่วยได้


เพื่อชี้แจงชี้แจงบิตในวงเล็บพาเรนติคอลที่ถูกเปลี่ยนเส้นทางไปยัง / dev / null นั้นเป็นสิ่งที่คุณต้องการ ทำให้คำสั่งไม่มี ouput และตรวจสอบสถานะข้อผิดพลาดโดยไม่ออกจากโปรแกรม
Addison Crump

0

ฉันต้องการเริ่ม subshell ถ้าต้องการเปลี่ยนบางสิ่งชั่วคราว ด้านล่างคำสั่งแสดงให้เห็นว่า bad_command แรกจะถูกละเว้นและยกเลิกการทำงานที่สอง

bash -c 'set -e ;\
( set +e; bad_command ; echo still here ) ;\
echo even here ; \
bad_command ; \
echo but not here;'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.