đặt -e trong một khung con


8

Tôi nghĩ rằng set -ecó tác dụng tương tự đối với các lớp con như trên lớp vỏ cấp cao nhất. Rõ ràng là không. Điều này:

(
  set -e
  false 
  true
) || echo false1


bash -ec '
  set -e
  false 
  true
' || echo false2


bash <<EOF || echo false3
  set -e
  false 
  true
EOF

bash <<EOF || echo false4
  false 
  true
EOF

bash <<EOF || echo false5
  false  &&
  true
EOF

Bản in

false2
false3
false5

Tài liệu này ở đâu? Tôi có thể nhận được các chuỗi con để chấm dứt lỗi, mà không kết nối tất cả các lệnh của chúng với &&(hoặc không thực hiện || exit $?sau mỗi lệnh) không?

Biên tập:

Trường hợp sử dụng cụ thể của tôi là một cái gì đó như:

set -e
  # ...
status=0
( false; true ) || status=$?
report_code $status
return $status

Trong đó nội dung của subshell là mã thực tế của tôi. Vấn đề với điều này là nó luôn đặt trạng thái thành 0 và thay thế || bằng ;nguyên nhân thoát lỗi không mong muốn do tập hợp bên ngoài -e.

Tôi đã giải quyết nó bằng:

set -e
  # ...
set +e
( false; true ); status=$?
set -e
report_code $status
return $status

Tôi ước tôi đã không phải làm điều này, nhưng nó xuất hiện tất cả các shell thông thường cho thấy sự phân đôi giữa thực thi và phân tách chỉ phụ này:

#!/bin/sh

echo FORK\'D:
export SH
for SH in dash bash ksh zsh; do
    $SH -c 'st=0; ( set -e; false; true ) || st=$?; printf "%s\t%s\n" $SH  $st; '
done

echo EXEC\'D:
for SH in dash bash ksh zsh; do
    $SH -c 'st=0; '$SH' -c " set -e; false; true " || st=$?; printf "%s\t%s\n" $SH $st; '
done

ĐẦU RA:

FORK'D:
dash    0
bash    0
ksh 0
zsh 0
EXEC'D:
dash    1
bash    1
ksh 1
zsh 1

1
Đó là dự định, đọc -ephần tài liệu của bộ .
cuonglm

Câu trả lời:


13

Quan sát:

$ ( set -e; false ; true ) || echo false1
$ ( set -e; false ; true ) ; echo code=$?
code=1

Cũng thế:

$ ( set -e; false ; true; echo inside=$? ) || echo false1
inside=0

Rõ ràng, khi lớp con được theo sau bởi a ||, set -ekhông làm cho lớp con thoát ra khi đạt được falselệnh. Thay vào đó, lớp con tiếp tục và thực thi true(và echo inside=$?).

Các triết lý set -ethường là nó chỉ thoát khỏi các lỗi chưa được phát hiện. Ở đây, sự hiện diện của ||bên ngoài lớp vỏ dường như cho lớp vỏ biết rằng lỗi bên trong lớp con bị 'bắt' và do đó set -ekhông gây ra lối ra sau false.

set -ecó nhiều hành vi đáng ngạc nhiên. Xem "Tại sao không đặt -e làm những gì tôi mong đợi?"

Tài liệu

Các hành vi trên được gợi ý trong tài liệu trong man bash:

-e

Thoát ngay lập tức nếu một đường ống (có thể bao gồm một lệnh đơn giản), danh sách hoặc lệnh ghép (xem SHELL GRAMMAR ở trên), thoát với trạng thái khác không. Shell không thoát nếu lệnh bị lỗi là một phần của danh sách lệnh ngay sau một từ khóa hoặc cho đến khi từ khóa, một phần của kiểm tra theo các từ dành riêng if hoặc elif, một phần của bất kỳ lệnh nào được thực thi trong && hoặc || danh sáchngoại trừ lệnh theo sau && hoặc ||, bất kỳ lệnh nào trong đường ống ngoại trừ lệnh cuối cùng hoặc nếu giá trị trả về của lệnh đang được đảo ngược với !. Nếu một lệnh ghép không phải là một lớp con trả về trạng thái khác không vì lệnh bị lỗi trong khi -e bị bỏ qua, shell sẽ không thoát. Một cái bẫy trên ERR, nếu được đặt, được thực thi trước khi thoát vỏ. Tùy chọn này áp dụng riêng cho môi trường hệ vỏ và từng môi trường lớp con riêng biệt (xem MÔI TRƯỜNG THỰC HIỆN QUY TẮC ở trên) và có thể khiến các lớp con thoát ra trước khi thực hiện tất cả các lệnh trong lớp con. [Nhấn mạnh thêm.]


"Triết lý của tập -e thường là chỉ xuất hiện khi có lỗi chưa được phát hiện. Ở đây, sự hiện diện của | một lối thoát sau khi sai. " Có, nhưng lỗi bên trong subshell không được báo cáo. "false1" không được in. Nó chỉ che giấu lỗi, như thể set -ehoàn toàn không có hiệu lực.
Jonas Berlin

Bạn dường như đang nói về vụ án ( set -e; false ; true ) || echo false1. Subshell thoát với mã trả về của lần chạy lệnh cuối cùng. Vì ||triệt tiêu lối ra sau false, nên lệnh cuối cùng được thực thi trong lớp con là true. Do đó, false1không được in vì subshell thoát với mã trả về zero.
John1024
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.