Lưu mã thoát cho lần sau


15

Vì vậy, tôi có một kịch bản nhỏ để chạy một số thử nghiệm.

javac *.java && java -ea Test
rm -f *.class

Bây giờ vấn đề với điều này là khi tôi chạy tập lệnh ./test, nó sẽ trả về mã thoát thành công ngay cả khi thử nghiệm thất bại vì rm -f *.classthành công.

Cách duy nhất tôi có thể nghĩ là khiến nó làm điều tôi muốn cảm thấy xấu xí với tôi:

javac *.java && java -ea Test
test_exit_code=$?
rm -f *.class
if [ "$test_exit_code" != 0 ] ; then false; fi

Nhưng điều này có vẻ như là một vấn đề phổ biến - thực hiện một nhiệm vụ, dọn dẹp, sau đó trả lại mã thoát của nhiệm vụ ban đầu.

Cách thành ngữ nhất để làm điều này (trong bash hoặc chỉ vỏ nói chung) là gì?

Câu trả lời:


5

Bạn có thể gói exitrmcác lệnh thành một lệnh đơn giản evalnhư:

java ... && java ...
eval "rm -f *.class; exit $?"

$?Giá trị của cách đó khi được chuyển đến exitlà bất cứ thứ gì nó được gán ngay trước khi evalchạy.


evalluôn được người hâm mộ yêu thích.
mikeerv

23

Tôi sẽ đi với:

javac *.java && java -ea Test
test_exit_code=$?
rm -f *.class
exit "$test_exit_code"

Tại sao nhảy xung quanh khi exitcó sẵn?


Bạn có thể sử dụng một trap:

trap 'last_error_code=$?' ERR

Ví dụ:

$ trap 'last_error_code=$?' ERR
$ false
$ echo $?
1
$ echo $last_error_code $?
1 0

Ah tôi đồng ý nó tốt hơn bản gốc của tôi. Nhưng tôi vẫn cảm thấy không thỏa đáng khi tôi phải lưu trữ mã thoát một cách rõ ràng vào một biến. Có cách nào để 'đẩy' mã thoát và 'bật lại' sau không?
math4tots

@ math4tots Hãy thử cập nhật.
muru

Vì vậy, với bản cập nhật của bạn, tôi sẽ phải khởi tạo last_error_code thành 0 và sau đó trả về ở cuối để tôi có mã thoát khác không nếu có lệnh nào gây ra lỗi? Đó là một mẹo hay, nhưng đối với kịch bản hack hai dòng của tôi, tôi nghĩ rằng tôi thích câu trả lời của @mikeerv.
math4tots

@ math4tots Bạn luôn có thể làm exit ${last_error_code:=0}.
muru

@avip để làm gì? Nó đã có trong dấu ngoặc đơn, vì vậy biến chỉ được đánh giá khi bẫy được gọi.
muru

9

Theo như tôi biết thì bash gần nhất có một try...finallykhối từ ngôn ngữ lập trình giống C hơn (đó là điều bạn có thể muốn nếu nó có sẵn) là trapcông trình, hoạt động như thế này:

trap "rm -f *.class" EXIT
javac *.java && java -ea Test

Điều này sẽ thực thi "rm -f *. Class" khi tập lệnh của bạn thoát. Nếu bạn có việc gì đó phức tạp hơn để làm, bạn có thể đặt nó vào một hàm:

cleanup() {
    ...
}
trap cleanup EXIT
javac *.java && java -ea Test

Nếu bạn rất có khuynh hướng, bạn có thể biến điều này thành một thành ngữ khá chung chung hoạt động gần giống như một try...catch...finallykhối trong C. Một cái gì đó như thế này:

(
  trap "catch_block; exit" ERR
  trap finally_block EXIT
  # contents of try goes here
)

Lưu ý rằng dấu ngoặc đơn phân định một nhánh con; với cấu trúc này, chỉ có lớp con thoát ra nếu một lệnh thất bại, không phải toàn bộ tập lệnh. Hãy nhớ rằng các mạng con có phần đắt tiền về mặt tính toán, vì vậy đừng sử dụng quá nhiều (hàng trăm) trong số chúng. Tùy thuộc vào tập lệnh của bạn, bạn có thể đạt được hiệu ứng tương tự hiệu quả hơn với các hàm shell và trap ... RETURN, nhưng điều đó tùy thuộc vào bạn để điều tra.

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.