Tại sao lệnh lệnh mô hình | | đúng là hữu ích?


79

Tôi hiện đang khám phá các gói Debian và tôi đã đọc một số mẫu mã. Và trên mỗi dòng trong, ví dụ, postinsttập lệnh là một mẫu.

some command || true
another command || true

Vì vậy, nếu một số lệnh thất bại, thì dòng trả về đúng nhưng tôi không thấy điều này ảnh hưởng đến đầu ra của chương trình.


5
FYI, ||:là một cách khác để thành ngữ của văn bản này ( :là một mục khác trong bảng BUILTIN trỏ đến true- nhưng đảm bảo là một BUILTIN thậm chí trở lại Bourne; mà nói, đối với POSIX sh, truelà tương tự như vậy đảm bảo được một dựng sẵn - vì vậy nó căng thẳng hơn hiệu quả trong thời gian thậm chí từ xa-hiện đại).
Charles Duffy

Câu trả lời:


151

Lý do cho mẫu này là các tập lệnh bảo trì trong các gói Debian có xu hướng bắt đầu set -e, khiến cho trình bao thoát ra ngay khi bất kỳ lệnh nào (nói đúng, đường ống, danh sách hoặc lệnh ghép) thoát ra với trạng thái khác không. Điều này đảm bảo rằng các lỗi không tích lũy: ngay khi có sự cố xảy ra, tập lệnh sẽ hủy bỏ.

Trong trường hợp một lệnh trong tập lệnh được phép thất bại, việc thêm || trueđảm bảo rằng lệnh ghép kết quả luôn thoát với trạng thái 0, vì vậy tập lệnh không hủy bỏ. Ví dụ: xóa thư mục không phải là lỗi nghiêm trọng (ngăn gói bị xóa); vì vậy chúng tôi sẽ sử dụng

rmdir ... || true

rmdirkhông có tùy chọn để bảo nó bỏ qua lỗi.


4
Chà, set -ekhông cần thiết chút nào || true, tôi nghĩ điều quan trọng là cung cấp bối cảnh. Nếu bạn nhận thấy những điều kỳ lạ trên POWER, tôi khuyến khích bạn nên báo cáo lỗi ( reportbug)!
Stephen Kitt

16
@MichaelFelt, thực sự set -ekhông chỉ là "quy ước Debian", mà còn phải sử dụng một mẫu lập trình tốt. Xem. ví dụ: davidpashley.com/articles/wr-robust-shell-scripts
kay

2
theo câu hỏi ở đây - tại sao sử dụng || trueset -e là bối cảnh có khả năng và có khả năng phổ biến nhất. Tôi cúi đầu trước câu trả lời này! Mặc dù theo nghĩa đen, nó hữu ích bất cứ lúc nào trạng thái thoát được coi là không liên quan VÀ (như liên kết bài viết của bạn thêm) Tôi không sử dụng trạng thái thoát như một phần của kiểm soát tập lệnh của mình. Tôi thấy tiện ích (trong set -e) nhưng sẽ không đi xa như bài viết và nói "Mỗi tập lệnh bạn viết nên bao gồm tập -e ở trên cùng". Đó là một phong cách lập trình. "LUÔN LUÔN | Mỗi" bao gồm một bộ bẫy riêng - hay còn gọi là tuyệt đối: các giải pháp thẻ hoang dã sẽ ALWAYSphản tác dụng cuối cùng hay còn gọi là - không có các chuyến đi miễn phí.
Michael Feel

1
@Kay Đó là một viễn cảnh phổ biến hiện nay nhưng cuối cùng lại bị sa lầy với nhiều giả định làm hạn chế tính di động của kịch bản. Có những mâu thuẫn lịch sử với set -ehành vi. Nó có thể không quan trọng với bạn, nếu các mục tiêu duy nhất của bạn là bashvà các lớp vỏ tương đối gần đây khác đang tồn tại /bin/sh, nhưng tình huống sẽ có nhiều sắc thái hơn khi bạn muốn hỗ trợ các hệ thống / hệ thống cũ.
mtraceur

2
@StephenKitt Chắc chắn rồi. Có một trangset -e rất kỹ lưỡng ghi lại các hành vi của các loại vỏ khác nhau của Sven Mascheck , mặc dù trang này cũng ghi lại rất nhiều vỏ sò lịch sử / cổ đại không liên quan ngày nay. Ngoài ra còn có hai trang này với trọng tâm hiện đại hẹp hơn (tìm kiếm "set -e"): trang "lintsh" , tài liệu về vỏ di động của autoconf -> Giới hạn trang
con của Buildins

32

Mặc dù nó không ảnh hưởng đến đầu ra của chương trình chỉ chạy - nó cho phép người gọi tiến hành như thể tất cả đều ổn hay còn ảnh hưởng đến logic trong tương lai.

Rephrased: nó che dấu trạng thái lỗi của lệnh trước đó.

michael@x071:[/usr/sbin]cat /tmp/false.sh
#!/bin/sh
false

michael@x071:[/usr/sbin]cat /tmp/true.sh 
#!/bin/sh
false || true

michael@x071:[/usr/sbin]sh /tmp/false.sh; echo $?
1
michael@x071:[/usr/sbin]sh /tmp/true.sh; echo $? 
0

6
Điều đó đúng, nhưng nó không trả lời tại sao che giấu trạng thái thoát lệnh là hữu ích.
moopet

4
set -e có nghĩa là tập lệnh sẽ chấm dứt ngay lập tức khi trả về giá trị khác không. Bạn có thể, ở vị trí địa phương đó, không muốn điều đó xảy ra!
rackandboneman

Tôi là một người đơn giản - và đối với tôi lý do duy nhất để che giấu tình trạng lỗi là vì đó là "theo cách". set -e gây ra bất kỳ lỗi nào "theo cách" nếu trước đó bạn không quan tâm. Tôi thích cuộc thảo luận vì tôi thấy đó là một cách hay để giúp tôi gỡ lỗi các tập lệnh của mình và viết logic bổ sung để phản hồi lỗi (ví dụ: | | in - "xxx tồn tại khác không ở đây". Hàm shell 'fatal' và tôi có "cái gì đó || gây tử vong" không vui cho tôi ". Imho một kịch bản nên báo cáo tình trạng không thành công hoặc không quan tâm. -e plus || đúng là che giấu lỗi. Nếu đó là điều tôi muốn - tốt thôi, nếu không, tôi đang thiếu lỗi
Michael Feel

điều tôi phải tự hỏi mình là: | | đúng - một cái nạng mã hóa (cách lười biếng để khắc phục / vượt qua lỗi mà tôi không muốn xử lý bây giờ; một công cụ gỡ lỗi (-e nhưng không | | đúng) hoặc chỉ là giáo điều của ai đó về thực hành mã hóa tốt là gì. - Tôi thấy nó là một tính năng - với lợi ích tiềm năng. Tôi không xem nó như một cây đũa thần để chữa trị tất cả. Nói tóm lại - giống như vẻ đẹp trong mắt của kẻ si tình - set -e|| truetiện ích sẽ được xác định bởi những đặc điểm và mục tiêu của lập trình viên.
Michael Feel

6
@MichaelFelt Xem xét: git remote remove foo || true git remote add foo http://blah- chúng tôi muốn bỏ qua lỗi nếu điều khiển từ xa không tồn tại.
dùng253751
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.