Làm thế nào để dừng tập lệnh bash khi một điều kiện không thành công?


11

Ở đây nó cho thấy sử dụng ||&&trong một dòng duy nhất để ghép nối việc thực thi các lệnh: Làm cách nào tôi có thể kiểm tra lỗi apt-get trong tập lệnh bash?

Tôi đang cố gắng dừng thực thi tập lệnh nếu một điều kiện nào đó không thành công,

ví dụ

false || echo "Obvious error because its false on left" && exit

Ở đây nó in Obvious error because its false on the leftvà thoát khỏi giao diện điều khiển đó là những gì tôi muốn.

true || echo "This shouldn't print" && exit

Ở đây, không có in echo nhưng exitlệnh cũng chạy, tức là giao diện điều khiển bị đóng, không nên exitlệnh không chạy vì lệnh echo bên phải không được thực thi? Hoặc theo mặc định là một tuyên bố được coi là sai ở phía bên trái của một &&toán tử?

Chỉnh sửa: Đáng lẽ tôi nên đề cập đến nó trước đây, mục đích của tôi là lặp lại lỗi và thoát nếu nó không rõ ràng. viết cho trường hợp cụ thể của tôi về việc bắt lỗi khi nhóm các điều kiện bằng cách sử dụng && và ||, @ bodhi.zazen trả lời giải quyết vấn đề.

@takatakatek trả lời làm cho rõ ràng hơn về kiểm soát dòng chảy và các liên kết hướng dẫn bash là tuyệt vời

Câu trả lời @muru có lời giải thích tốt về lý do tại sao không sử dụng set -e nếu bạn muốn gửi thông báo lỗi tùy chỉnh với các lựa chọn thay thế sử dụng perl và bẫy mà tôi nghĩ là một cách mạnh mẽ hơn và xem bản thân sử dụng nó từ tập lệnh bash thứ hai trở đi!


Theo như tôi có thể nói nó thoát khi kịch bản được thực hiện.
Panther

Câu trả lời:


10

Bạn có thể muốn (như được chỉ ra bởi Steeldo)

true || { echo "This shouldn't print" && exit; }

Nếu không, kịch bản của bạn đang đọc một điều kiện tại một thời điểm

a hoặc b và sau đó thoát

Tôi nghĩ bạn muốn một hoặc (b và thoát)?


4
Trên thực tế, bạn phải sử dụng { ... ; }(như @steel ấn đã đề xuất), nếu không thì exitchỉ thoát ra khỏi lớp con và shell cha tiếp tục thực thi tập lệnh.
Gordon Davisson

14

Vấn đề là | | và && chỉ bỏ qua một khổ tiếp theo của chuỗi lệnh khi điều kiện không thành công. Nếu bạn viết ra một cấu trúc khối đầy đủ, nó có ý nghĩa hoàn hảo. Những gì bạn đã viết trở thành này:

if ! true ; then
   echo "This shouldn't print"
else
   exit
fi

Những gì bạn muốn là đây:

if ! true ; then
   echo "This shouldn't print"
   exit
fi

Khi bạn đang sử dụng các toán tử điều kiện tắt của Bash, tốt hơn là tránh trộn chúng. Logic dễ hiểu hơn nhiều trong khi bạn viết nó và độc giả của bạn sẽ đánh giá cao phong cách tốt của bạn.


2
Vâng, theo ý kiến ​​của tôi, đây là cách viết điều hòa trong bash nhiều hơn
derHugo

@takatakatek Điều này làm cho nó rõ ràng hơn tại sao nó thất bại trong trường hợp của tôi. Tôi đồng ý rằng logic này rõ ràng trong phần này nhưng không phải là lý do để nhóm các điều kiện sử dụng && và || là để tránh thể hiện chúng bằng cách sử dụng các câu điều kiện?
kosol

@kosol Có, && và || kết hợp hai điều: Kiểm tra trạng thái thoát của lệnh trước đó và chỉ định một lệnh (hoặc nhóm lệnh) sẽ được thực thi (cho &&) hoặc bỏ qua (cho | |). Chúng có thể hữu ích cho các trường hợp rất đơn giản, nhưng chúng không thể thay thế if ... then ... elif ... else ... ficác khối được thể hiện đầy đủ . Tôi nghi ngờ bạn có thể không nhận thức được rằng Bash không có các kiểu boolean thực sự được thấy trong các ngôn ngữ phức tạp hơn. Nếu trạng thái thoát của lệnh là 0 (không), Bash coi đó là đúng / thành công . Nếu trạng thái thoát là khác không, Bash coi đó là sai / thất bại .
takatakatek

7

Cách đơn giản nhất để không gặp lỗi là sử dụng -etùy chọn của bash ( set -ehoặc /bin/bash -etrong shebang). Tuy nhiên, điều này không giúp bạn dễ dàng gửi thông báo lỗi tùy chỉnh. Có một vài thành ngữ có thể làm cho nó đơn giản hơn:

die à la Perl

Perl có một dielệnh rất thuận tiện , in một thông điệp tới thiết bị lỗi chuẩn và đưa ra một ngoại lệ, điều này thường dẫn đến việc kết thúc tập lệnh. Bạn có thể mô phỏng điều này:

die () {
  ret=$?
  print "%s\n" "$@" >&2
  exit "$ret"
}

false || die "Obvious error because its false on left"
true || die "This shouldn't print"

trap ERR

Các trap <command>lệnh có thể được sử dụng để chạy một lệnh khi một tín hiệu nhận được, hoặc khi thoát khỏi kịch bản ( trap ... EXIT), hoặc khi một lệnh trả về một lỗi ( trap ... ERR). Vì vậy, một cái gì đó như:

trap 'ret=$?; printf "%s\n" "$ERR_MSG" >&2; exit "$ret"' ERR

Sau đó:

ERR_MSG="Obvious error because its false here"
false
ERR_MSG="This shouldn't print"
true

Trong cả hai trường hợp, tôi khuyên bạn nên sử dụng ít nhất exit 1, để chỉ ra rằng tập lệnh thất bại . Một đồng bằng exitsẽ sử dụng trạng thái thoát của lệnh trước đó, trong các trường hợp này sẽ là lệnh echohoặc printf, thường sẽ thành công. Lưu trạng thái thoát của lệnh thất bại như tôi đã làm ở đây sẽ là một việc tốt để có.


6

Bạn có thể thử trải nghiệm một chút với việc bắt đầu tập lệnh với

#!/bin/bash -e

-E đảm bảo rằng tập lệnh thoát khỏi thời điểm một cái gì đó trả về sai. Một thất bại cụ thể sau đó có thể tránh được vớisomething || true

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.