Nếu bạn thực sự không muốn lệnh thứ hai tiếp tục cho đến khi lệnh đầu tiên được biết là thành công, thì bạn có thể cần sử dụng các tệp tạm thời. Phiên bản đơn giản của nó là:
tmp=${TMPDIR:-/tmp}/mine.$$
if ./a > $tmp.1
then
if ./b <$tmp.1 >$tmp.2
then
if ./c <$tmp.2
then : OK
else echo "./c failed" 1>&2
fi
else echo "./b failed" 1>&2
fi
else echo "./a failed" 1>&2
fi
rm -f $tmp.[12]
Chuyển hướng '1> & 2' cũng có thể được viết tắt '> & 2'; tuy nhiên, một phiên bản cũ của MKS shell đã xử lý sai chuyển hướng lỗi mà không có '1' trước đó, vì vậy tôi đã sử dụng ký hiệu rõ ràng đó để đảm bảo độ tin cậy cho các lứa tuổi.
Điều này làm rò rỉ các tệp nếu bạn làm gián đoạn điều gì đó. Lập trình shell chống bom (nhiều hơn hoặc ít hơn) sử dụng:
tmp=${TMPDIR:-/tmp}/mine.$$
trap 'rm -f $tmp.[12]; exit 1' 0 1 2 3 13 15
...if statement as before...
rm -f $tmp.[12]
trap 0 1 2 3 13 15
Dòng bẫy đầu tiên cho biết 'chạy lệnh' rm -f $tmp.[12]; exit 1
khi bất kỳ tín hiệu nào 1 SIGHUP, 2 SIGINT, 3 SIGQUIT, 13 SIGPIPE hoặc 15 SIGTERM xảy ra hoặc 0 (khi shell thoát ra vì bất kỳ lý do gì). Nếu bạn đang viết script shell, thì bẫy cuối cùng chỉ cần gỡ bỏ bẫy về 0, đó là bẫy thoát shell (bạn có thể để nguyên các tín hiệu khác vì quá trình này sắp kết thúc).
Trong đường dẫn ban đầu, khả thi khi 'c' đọc dữ liệu từ 'b' trước khi 'a' kết thúc - điều này thường là mong muốn (ví dụ: nó cho phép nhiều lõi làm việc). Nếu 'b' là giai đoạn 'sắp xếp', thì điều này sẽ không áp dụng - 'b' phải xem tất cả đầu vào của nó trước khi nó có thể tạo ra bất kỳ đầu ra nào của nó.
Nếu bạn muốn phát hiện (các) lệnh nào không thành công, bạn có thể sử dụng:
(./a || echo "./a exited with $?" 1>&2) |
(./b || echo "./b exited with $?" 1>&2) |
(./c || echo "./c exited with $?" 1>&2)
Điều này đơn giản và đối xứng - việc mở rộng sang đường ống 4 phần hoặc N phần là điều nhỏ.
Thử nghiệm đơn giản với 'set -e' không giúp được gì.
&&|
vậy có nghĩa là "chỉ tiếp tục đường ống nếu lệnh trước đó thành công". Tôi cho rằng bạn cũng có thể có|||
, điều đó có nghĩa là "tiếp tục đường ống nếu lệnh trước đó không thành công" (và có thể chuyển thông báo lỗi như Bash 4|&
).