Thoát khỏi một kịch bản lỗi


141

Tôi đang xây dựng Shell Script có ifchức năng như thế này:

if jarsigner -verbose -keystore $keyst -keystore $pass $jar_file $kalias
then
    echo $jar_file signed sucessfully
else
    echo ERROR: Failed to sign $jar_file. Please recheck the variables
fi

...

Tôi muốn việc thực thi tập lệnh kết thúc sau khi hiển thị thông báo lỗi. Làm thế nào tôi có thể làm điều này?

Câu trả lời:


137

Bạn đang tìm kiếm exit?

Đây là hướng dẫn bash tốt nhất xung quanh. http://tldp.org/LDP/abs/html/

Trong ngữ cảnh:

if jarsigner -verbose -keystore $keyst -keystore $pass $jar_file $kalias
then
    echo $jar_file signed sucessfully
else
    echo ERROR: Failed to sign $jar_file. Please recheck the variables 1>&2
    exit 1 # terminate and indicate error
fi

...

5
Nếu bạn thích ABS, bạn sẽ thích BashGuide , BashFAQBashPit thác .
Tạm dừng cho đến khi có thông báo mới.

Những liên kết Bash là TUYỆT VỜI! BashFAQ sẽ được định vị tốt hơn là BashRecipes.
Pete Alvin

337

Nếu bạn đặt set -emột tập lệnh, tập lệnh sẽ chấm dứt ngay khi bất kỳ lệnh nào bên trong nó bị lỗi (tức là ngay khi bất kỳ lệnh nào trả về trạng thái khác không). Điều này không cho phép bạn viết tin nhắn của riêng mình, nhưng thường thì tin nhắn của lệnh bị lỗi là đủ.

Ưu điểm của phương pháp này là nó tự động: bạn không có nguy cơ quên xử lý trường hợp lỗi.

Các lệnh có trạng thái được kiểm tra bởi một điều kiện (chẳng hạn như if, &&hoặc ||) không chấm dứt tập lệnh (nếu không thì điều kiện sẽ là vô nghĩa). Một thành ngữ cho lệnh thỉnh thoảng có lỗi không thành vấn đề command-that-may-fail || true. Bạn cũng có thể set -etắt cho một phần của tập lệnh set +e.


3
Theo mywiki.wooledge.org/BashFAQ/105 - tính năng này có lịch sử bị che khuất và bị sai khiến khi xác định mã lỗi của lệnh nào gây ra thoát tự động. Hơn nữa, "các quy tắc thay đổi từ phiên bản Bash này sang phiên bản khác, khi Bash cố gắng theo dõi định nghĩa POSIX cực kỳ trơn trượt của 'tính năng' này". Tôi đồng ý với @Dennis Williamson và câu trả lời được chấp nhận của stackoverflow.com/questions/19622198/ - sử dụng bẫy 'error_handler' ERR. Ngay cả khi đó là một cái bẫy!
Bondolin

3
thường sử dụng -xcờ với -ecờ là đủ dấu vết về nơi chương trình của bạn đang thoát. Điều đó ngụ ý rằng người sử dụng tập lệnh cũng là nhà phát triển.
Alex

Đẹp nhưng tôi nghĩ OP cần phải thoát khỏi tập lệnh từ một ngoại lệ tự xác định.
vdegenne

42

Nếu bạn muốn để có thể xử lý một lỗi thay vì mù quáng thoát, thay vì sử dụng set -e, sử dụng một traptrên ERRtín hiệu giả.

#!/bin/bash
f () {
    errorCode=$? # save the exit code as the first thing done in the trap function
    echo "error $errorCode"
    echo "the command executing at the time of the error was"
    echo "$BASH_COMMAND"
    echo "on line ${BASH_LINENO[0]}"
    # do some error handling, cleanup, logging, notification
    # $BASH_COMMAND contains the command that was being executed at the time of the trap
    # ${BASH_LINENO[0]} contains the line number in the script of that command
    # exit the script or return to try again, etc.
    exit $errorCode  # or use some other value or do return instead
}
trap f ERR
# do some stuff
false # returns 1 so it triggers the trap
# maybe do some other stuff

Các bẫy khác có thể được đặt để xử lý các tín hiệu khác, bao gồm các tín hiệu Unix thông thường cộng với các tín hiệu giả Bash khác RETURNDEBUG.


8

Đây là cách để làm điều đó:

#!/bin/sh

abort()
{
    echo >&2 '
***************
*** ABORTED ***
***************
'
    echo "An error occurred. Exiting..." >&2
    exit 1
}

trap 'abort' 0

set -e

# Add your script below....
# If an error occurs, the abort() function will be called.
#----------------------------------------------------------
# ===> Your script goes here
# Done!
trap : 0

echo >&2 '
************
*** DONE *** 
************
'

Tại sao tin nhắn DONE đến stderr?
MattBianco

1
Đây là một thực tế phổ biến để bạn có thể chuyển đầu ra tập lệnh của mình thành thiết bị xuất chuẩn để một quy trình khác có thể nhận được nó mà không có thông báo thông tin ở giữa.
siêu xe

2
Nó có lẽ là thực tế phổ biến như nhau để coi bất cứ điều gì trên stderr như là một dấu hiệu của vấn đề.
MattBianco

1
Trước đây, 'set -e' luôn có tác dụng với tôi, nhưng tối nay tôi tình cờ gặp một tình huống trong hình ảnh Docker của Linux Linux, nơi nó không có tác dụng .. Giải pháp này hiệu quả với tôi và giúp tôi hoàn thành nhiệm vụ. Nhiều đánh giá cao.
tổng

@supercobra Thực hành phổ biến? Ở đâu?
Thorbjørn Ravn Andersen

-8

exit 1là tất cả những gì bạn cần. Đây 1là một mã trả về, vì vậy bạn có thể thay đổi nó nếu bạn muốn, 1có nghĩa là chạy thành công và -1có nghĩa là một thất bại hoặc một cái gì đó tương tự.


13
Trong unix, thành công luôn là 0. Điều này có thể giúp khi sử dụng testhay &&hay ||.
mouviciel

5
Để mở rộng nhận xét của mouviciel: trong các tập lệnh shell, 0 luôn có nghĩa là thành công và 1 đến 255 có nghĩa là thất bại. -1 nằm ngoài phạm vi (và thường sẽ có hiệu ứng tương tự như 255, do đó, thất bại như 1).
Gilles 'SO- ngừng trở nên xấu xa'

@mouviciel, @Gilles: Cảm ơn bạn đã biết thêm thông tin. Đã được một thời gian kể từ khi tôi xử lý bash.
DGH

Đây là một ví dụ tồi về việc sử dụng mã trả về, nếu không nó sẽ là một câu trả lời tuyệt vời.
Brad Koch

1
Ngoài việc đề xuất không chính xác 1 cho thành công, -1 là không thể (mã thoát không được ký).
tripleee
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.