Làm cách nào để tắt set -e cho một lệnh riêng lẻ?


36

Lệnh set -e làm cho tập lệnh bash bị lỗi ngay lập tức khi bất kỳ lệnh nào trả về mã thoát khác không.

  1. Có cách nào dễ dàng và tao nhã để vô hiệu hóa hành vi này cho một lệnh riêng lẻ trong tập lệnh không?

  2. Những vị trí này được ghi lại trong Tài liệu tham khảo Bash ( http://www.gnu.org/software/bash/manual/bashref.html )?

Câu trả lời:


29
  1. Một cái gì đó như thế này:

    #!/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

    Chạy:

    $ ./test.sh
    hi
    ./test.sh: line 7: aoeuidhtn: command not found
    next line
    ./test.sh: line 11: ao: command not found
  2. Nó được mô tả trong phần settrợ giúp dựng sẵn:

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

Điều tương tự cũng được ghi lại ở đây: https://www.gnu.org/software/bash/manual/bashref.html#The-set-Builtin .


Cảm ơn! Tôi đã tìm thấy một khả năng khác: #! / Bin / bash set -e # Uncomment dòng tiếp theo để xem hiệu ứng set -e: #blubb if blubb; sau đó lặp lại "Lệnh blubb đã thành công." khác echo "Lệnh blubb không thành công. Mã thoát: $?" fi echo thoát tập lệnh thông thường
Gustave

22

Một giải pháp thay thế cho việc bỏ đặt tiền bảo lãnh có lỗi sẽ là thành công cho dù điều gì xảy ra. Bạn có thể làm một cái gì đó như thế này:

cmd_to_run || true

Điều đó sẽ trả về 0 (đúng), vì vậy tập hợp -e không nên được kích hoạt


3
faulty_cmd || :là một thành ngữ phổ biến cho việc này. (Đây :là một lệnh đồng nghĩa với true).
ulidtko

3
@ulidtko - thú vị. Dẫn tôi xuống hố thỏ để tìm stackoverflow.com/questions/3224878/ này để có được lịch sử trên so với:
ernie

12

Nếu bạn đang cố bắt mã trả về / lỗi (hàm hoặc ngã ba), thì điều này hoạt động:

function xyz {
    return 2
}

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

8

Nếu "tùy chọn thoát ngay lập tức shell" áp dụng hoặc bị bỏ qua tùy thuộc vào ngữ cảnh của lệnh được thực thi (xem phần Hướng dẫn tham khảo Bash trên Set dựng sẵn - nhờ Arkadiusz Drabchot).

Đặc biệt, tùy chọn bị bỏ qua nếu một lệnh là một phần của kiểm tra trong câu lệnh if. Do đó, có thể thực thi một lệnh và kiểm tra thành công hay thất bại của nó trong "thoát khỏi bối cảnh ngay lập tức" bằng cách sử dụng câu lệnh if như sau:

#!/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."

Có thể bỏ qua câu lệnh "then" và sử dụng ít dòng hơn:

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

2

Một cách tiếp cận khác, mà tôi thấy khá đơn giản (và áp dụng cho các settùy chọn khác ngoài -e):

Sử dụng $-để khôi phục cài đặt.

Ví dụ:

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

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

Mặc dù -ecụ thể, các tùy chọn mà người khác đã đề cập ( || truehoặc "đặt bên trong một if") có thể là thành ngữ hơn.


0

Tôi thực sự có một câu hỏi tương tự gần đây (mặc dù tôi không đăng, tôi đã giải quyết nó), và, từ những gì tôi có thể thấy, có vẻ như chỉ sử dụng set + e trước khi lệnh và set -e sau đó hoạt động một cách thanh lịch nhất. Đây là một ví dụ, lấy phản hồi của lệnh và không để lỗi ném đi.

#!/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

Cái này lấy đầu ra của 'vận may', kiểm tra trạng thái thoát của nó và lặp lại và nói nó. Tôi nghĩ rằng đây là những gì bạn đã yêu cầu, hoặc ít nhất là một cái gì đó tương tự? Dù sao, hy vọng điều này sẽ giúp.


Để làm rõ, bit trong các ngoặc đơn xoăn được chuyển hướng đến / dev / null là những gì bạn đang theo đuổi, tôi tin. Nó làm cho lệnh không có thông số và kiểm tra trạng thái lỗi của nó mà không thoát khỏi chương trình.
Addison Crump

0

Tôi muốn bắt đầu subshell nếu muốn thay đổi một cái gì đó tạm thời. Lệnh dưới đây chứng minh rằng bad_command đầu tiên bị bỏ qua và thực hiện hủy bỏ thứ hai.

bash -c 'set -e ;\
( set +e; bad_command ; echo still here ) ;\
echo even here ; \
bad_command ; \
echo but not here;'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.