Đây là một câu hỏi cũ, nhưng không có câu trả lời nào ở đây thảo luận về việc sử dụng set -e
aka set -o errexit
trong các tập lệnh xử lý gói Debian. Việc sử dụng tùy chọn này là bắt buộc trong các tập lệnh này, theo chính sách Debian; mục đích rõ ràng là để tránh bất kỳ khả năng của một điều kiện lỗi chưa được xử lý.
Điều này có nghĩa là gì trong thực tế là bạn phải hiểu trong những điều kiện nào các lệnh bạn chạy có thể trả về một lỗi và xử lý rõ ràng từng lỗi đó.
Gotchas phổ biến là ví dụ diff
(trả về lỗi khi có sự khác biệt) và grep
(trả về lỗi khi không có kết quả khớp). Bạn có thể tránh các lỗi với xử lý rõ ràng:
diff this that ||
echo "$0: there was a difference" >&2
grep cat food ||
echo "$0: no cat in the food" >&2
(Cũng lưu ý cách chúng tôi chú ý bao gồm tên của tập lệnh hiện tại vào tin nhắn và viết thông báo chẩn đoán thành lỗi tiêu chuẩn thay vì đầu ra tiêu chuẩn.)
Nếu không có xử lý rõ ràng là thực sự cần thiết hoặc hữu ích, rõ ràng không làm gì:
diff this that || true
grep cat food || :
(Việc sử dụng :
lệnh no-op của shell hơi tối nghĩa, nhưng khá phổ biến.)
Chỉ cần nhắc lại,
something || other
là tốc ký cho
if something; then
: nothing
else
other
fi
tức là chúng tôi nói rõ ràng other
nên được chạy nếu và chỉ khi something
thất bại. Longhand if
(và các câu lệnh điều khiển luồng shell khác như while
, until
) cũng là một cách hợp lệ để xử lý lỗi (thực sự, nếu không, các tập lệnh shell với set -e
không bao giờ có thể chứa các câu lệnh điều khiển luồng!)
Và ngoài ra, chỉ cần nói rõ ràng, nếu không có trình xử lý như thế này, set -e
sẽ khiến toàn bộ tập lệnh bị lỗi ngay lập tức với một lỗi nếu diff
tìm thấy sự khác biệt hoặc nếu grep
không tìm thấy kết quả khớp.
Mặt khác, một số lệnh không tạo ra trạng thái thoát lỗi khi bạn muốn. Các lệnh thường gặp sự cố là find
(trạng thái thoát không phản ánh liệu các tệp có thực sự được tìm thấy hay không) và sed
(trạng thái thoát sẽ không tiết lộ liệu tập lệnh có nhận được bất kỳ đầu vào nào hay thực sự thực hiện bất kỳ lệnh nào thành công hay không). Một người bảo vệ đơn giản trong một số tình huống là chuyển sang một lệnh sẽ hét lên nếu không có đầu ra:
find things | grep .
sed -e 's/o/me/' stuff | grep ^
Cần lưu ý rằng trạng thái thoát của một đường ống là trạng thái thoát của lệnh cuối cùng trong đường ống đó. Vì vậy, các lệnh trên thực sự che dấu hoàn toàn trạng thái của find
và sed
, và chỉ cho bạn biết liệu grep
cuối cùng có thành công hay không.
(Tất nhiên, Bash có set -o pipefail
; nhưng các tập lệnh gói Debian không thể sử dụng các tính năng của Bash. Chính sách này hoàn toàn ra lệnh sử dụng POSIX sh
cho các tập lệnh này, mặc dù điều này không phải lúc nào cũng đúng.)
Trong nhiều tình huống, đây là điều cần chú ý riêng khi mã hóa phòng thủ. Đôi khi, bạn phải đi qua một tệp tạm thời để bạn có thể xem liệu lệnh tạo ra đầu ra đó đã kết thúc thành công hay chưa, ngay cả khi thành ngữ và sự thuận tiện sẽ hướng dẫn bạn sử dụng đường ống vỏ.