`{{(Lối ra 1); lối ra 1; }; } `có nghĩa là gì?


28

Tôi đã trích dẫn đoạn mã tiếp theo từ config.statusđược tạo bởi configure.

if test ! -f "$as_myself"; then
{ { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
{ (exit 1); exit 1; }; }
fi

Trong đoạn mã, { (exit 1); exit 1; };làm gì? Mục đích của việc chỉ làm exittrong một subshell là gì?

Câu trả lời:


33

Thực hiện (exit 1);là cách đơn giản nhất để kích hoạt một ERRcái bẫy. Nó cũng sẽ kích hoạt thoát ngay lập tức nếu set -ecó hiệu lực. (Kích hoạt điều kiện lỗi yêu cầu một lệnh thất bại; exitvới giá trị thất bại trong một lớp con làm cho lớp con bị lỗi.)

exit 1; sẽ không làm những điều đó.

Vì vậy, {(exit 1); exit 1;}trước tiên có thể được sử dụng để tạo ERRbẫy, có thể làm điều gì đó hữu ích cho mục đích gỡ lỗi và sau đó chấm dứt tập lệnh với dấu hiệu lỗi.

Nhưng đó không phải là những gì đang diễn ra trong autoconfcác tập tin. autoconfcác tập lệnh dựa vào EXITbẫy để dọn sạch các tệp tạm thời được tạo trong quá trình chạy. Hầu hết các shell, bao gồm bashsẽ đặt trạng thái từ giá trị được cung cấp trong exitlệnh trước khi gọi EXITbẫy. Điều đó có thể cho phép EXITbẫy phát hiện xem nó đã được gọi từ một lỗi hay từ chấm dứt bình thường, và nó cũng cho phép nó đảm bảo rằng trạng thái thoát được đặt chính xác vào cuối hoạt động bẫy.

Tuy nhiên, rõ ràng một số vỏ không hợp tác. Đây là một trích dẫn từ autoconfhướng dẫn :

Một số tập lệnh shell, chẳng hạn như tập lệnh được tạo bởi autoconf, sử dụng một cái bẫy để dọn sạch trước khi thoát. Nếu lệnh shell cuối cùng thoát với trạng thái khác 0, bẫy cũng thoát với trạng thái khác 0 để kẻ xâm lược có thể biết rằng đã xảy ra lỗi.

Thật không may, trong một số shell, như Solaris /bin/sh, một bẫy thoát bỏ qua đối số của lệnh thoát. Trong các shell này, một cái bẫy không thể xác định liệu nó được gọi bằng lối thoát đơn giản hay bằng lối thoát 1. Thay vì gọi trực tiếp lối ra, hãy sử dụng AC_MSG_ERRORmacro có cách giải quyết cho vấn đề này.

Cách giải quyết là để đảm bảo rằng $?có trạng thái thoát trước khi các exitlệnh được thực thi, do đó nó chắc chắn sẽ có giá trị mà khi EXITbẫy được thực thi. Và, thực sự, đó là AC_MSG_ERRORmacro chèn mã tò mò đó, hoàn chỉnh với các dấu ngoặc nhọn.


Tại sao không chỉ thực hiện falsethay vì (exit 1)?
Ruslan

3
@Ruslan: Hai vấn đề. (1) Quan trọng nhất: falsekhông cho phép bạn đặt mã trạng thái và không có gì đảm bảo về trạng thái khác không mà nó trả về. (2) falsethường không phải là nội dung, vì vậy nó đòi hỏi một quá trình con; ngược lại, hầu hết các vỏ có thể tránh sinh ra một đứa trẻ để xử lý (exit 1).
rici

8

Không có mục đích cho điều này như tôi có thể thấy, không có gì có thể đạt được trực tiếp bằng cách bắt đầu một subshell và sau đó thoát ra ngay lập tức.

Những thứ như thế này rất có thể là tác dụng phụ của việc tự động tạo mã - trong một số trường hợp, có thể có các lệnh khác được thực thi trong lớp con có exit 1ý nghĩa. Cuối cùng, rất có khả năng mã thế hệ được đơn giản hóa bằng cách nào đó bằng cách cho phép nó chèn một số câu lệnh không có bất kỳ chức năng nào trong một số trường hợp và tạo ra "mã sạch" mỗi lần phức tạp hơn. Hoặc là hoặc mã tạo ra ở trên chỉ được viết kém :)

Việc sử dụng tự do {...}là một ví dụ khác về điều này, hầu hết trong số chúng là dự phòng, nhưng việc viết mã chèn chúng trong mọi trường hợp sẽ dễ dàng hơn (có thể trong một số trường hợp bạn muốn chuyển hướng đầu ra / đầu vào của khối) thay vì phân biệt những nơi mà họ không cần thiết và bỏ qua chúng.


Nó có một mục đích. Xem câu trả lời của @ rici.
Old Pro

1

(exit 1)là một cách đơn giản, có lẽ là cách đơn giản nhất để có được một mã thoát nhất định (trong trường hợp đặc biệt là 1 có những cách dễ dàng hơn, tất nhiên). Nhưng đó không phải là lý do trong trường hợp này vì mã thoát không được kiểm tra.

Mục đích của việc đặt exitmột lớp con có thể là không thoát khỏi tập lệnh (mặc dù sử dụng lối ra để tạo mã thoát nhất định).

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.