Hành vi của những người khác đã bị bắt gặp


9

Hãy xem xét các lệnh

eval false || echo ok
echo also ok

Thông thường, chúng tôi hy vọng điều này sẽ thực thi falsetiện ích và, vì trạng thái thoát là khác không, sau đó thực thi echo okecho also ok.

Trong tất cả các POSIX giống như vỏ tôi sử dụng ( ksh93, zsh, bash, dash, OpenBSD ksh, và yash), đây là những gì xảy ra, nhưng mọi thứ trở nên thú vị nếu chúng tôi cho phép set -e.

Nếu set -ecó hiệu lực, OpenBSD shkshshell (cả hai đều xuất phát từ pdksh) sẽ chấm dứt tập lệnh khi thực thi eval. Không có vỏ khác làm điều đó.

POSIX nói rằng một lỗi trong một tiện ích tích hợp đặc biệt (chẳng hạn như eval) sẽ khiến lớp vỏ không tương tác chấm dứt. Tôi không hoàn toàn chắc chắn liệu việc thực thi có falsecấu thành "lỗi" hay không (nếu có, nó sẽ không phụ thuộc vào set -ehoạt động).

Cách để giải quyết vấn đề này dường như là đặt evalvỏ phụ,

( eval false ) || echo ok
echo also ok

Câu hỏi đặt ra là liệu tôi có phải làm điều đó trong tập lệnh shell chính xác POSIX-ly hay không, hay đó là một lỗi trong trình bao của OpenBSD? Ngoài ra, "lỗi" trong văn bản POSIX được liên kết ở trên có nghĩa là gì?


Thêm một chút thông tin: Các shell OpenBSD sẽ thực thi echo okcả có và không có set -e trong lệnh

eval ! true || echo ok

Mã ban đầu của tôi trông giống như

set -e
if eval "$string"; then
    echo ok
else
    echo not ok
fi

cái mà sẽ không xuất ra not okkhi string=falsesử dụng shell OpenBSD (nó sẽ chấm dứt) và tôi không chắc nó là do thiết kế, do nhầm lẫn hay do hiểu lầm, hay cái gì khác.


eval falsetạo ra một trạng thái khác không, vì vậy tôi dự kiến set -esẽ chấm dứt tập lệnh tại thời điểm đó. Trong trường hợp ! set -ekhông áp dụng như !câu lệnh kiểm tra rõ ràng trạng thái thoát.
fcbsd

@fcbsd Bạn có muốn eval falsechấm dứt tập lệnh ngay cả khi đó là một phần của danh sách AND-OR hoặc câu lệnh có điều kiện không? Tôi sẽ không.
Kusalananda

Tôi không chắc chắn nếu set -eđược đặt nếu đó là hành vi chính xác ... Tôi đồng ý rằng việc không chấm dứt trong một tuyên bố có điều kiện là hợp lý.
fcbsd

đã chơi nhiều hơn, với sh trên CentOS 7 - Tôi sẽ nói rằng đó là hành vi dành cho ksh / sh của OpenBSD khi sử dụng set -evì vậy `()` là câu trả lời.
fcbsd

Câu trả lời:


4

Không có shell nào khác cần cách giải quyết như vậy là một dấu hiệu mạnh mẽ cho thấy đó là một lỗi trong OpenBSD ksh. Trên thực tế, ksh93 không cho thấy vấn đề như vậy.

Rằng có một ||dòng lệnh phải tránh lối ra shell gây ra bởi mã trả về 1 ở bên trái của nó.

Lỗi của một tích hợp đặc biệt sẽ gây ra sự thoát khỏi lớp vỏ không tương tác theo POSIX nhưng điều đó không phải lúc nào cũng đúng. Cố gắng continuethoát khỏi một vòng lặp là một lỗi và continuelà một nội dung. Nhưng hầu hết các shell không thoát ra trên:

continue 3

Nội dung phát ra lỗi rõ ràng nhưng không thoát.

Vì vậy, lối ra trên falseđược tạo bởi set -eđiều kiện không phải bởi đặc tính dựng sẵn của lệnh ( evaltrong trường hợp này).

Các điều kiện chính xác set -esẽ thoát ra khá mờ trong POSIX.


Điều này lặp lại phản hồi mà tôi đã thoát khỏi danh sách gửi thư OpenBSD, nhưng với nhiều từ hơn, cảm ơn! Tôi sẽ sắp xếp một báo cáo lỗi thích hợp và nếu không có gì xảy ra, tôi sẽ tự mình xem mã nguồn.
Kusalananda

4

[xin lỗi nếu đây không phải là câu trả lời thực sự, tôi sẽ cập nhật nó khi tôi làm tròn nó]

Tôi đã xem mã nguồn và kết luận của tôi là:

1) Đó là một lỗi / giới hạn, không có gì triết lý đằng sau nó.

2) "Sửa" cho nó từ ngã ba di động của OpenBSD ksh ( mksh) rất kém, chỉ làm cho mọi thứ tồi tệ hơn mà không thực sự sửa nó:

Lỗi mới, khác với tất cả các shell khác:

mksh -ec 'eval "false; echo yup"'
yup

bash -ec 'eval "false; echo yup"'
(nothing)

Vẫn chưa thực sự cố định:

mksh -ec 'eval "set -e; false" || echo yup'
(nothing)

bash -ec 'eval "set -e; false" || echo yup'
yup

Bạn có thể thay thế bashở trên với dash, zsh, yash, ksh93vv

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.