Якщо ви дійсно не хочете, щоб друга команда тривала до тих пір, поки не буде відомо, що перша успішна, вам, ймовірно, потрібно використовувати тимчасові файли. Проста версія цього:
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]
Перенаправлення '1> & 2' також може бути скорочено '> & 2'; однак стара версія оболонки MKS неправильно керувала перенаправленням помилок без попереднього "1", тому я використовував це однозначне позначення для надійності для віків.
Це витікає файли, якщо ви щось перериваєте. Програмування оболонок, захищених від бомб (більше чи менше), використовує:
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
Перший рядок пастки говорить "запустити команди" rm -f $tmp.[12]; exit 1
, коли відбувається будь-який із сигналів 1 SIGHUP, 2 SIGINT, 3 SIGQUIT, 13 SIGPIPE або 15 SIGTERM або 0 (коли оболонка виходить з будь-якої причини). Якщо ви пишете сценарій оболонки, для остаточної пастки потрібно лише видалити пастку на 0, яка є пасткою для виходу з оболонки (ви можете залишити інші сигнали на місці, оскільки процес все-таки закінчиться).
У початковому конвеєрі "c" можливо зчитувати дані з "b" до того, як "a" закінчиться - зазвичай це бажано (наприклад, це дає декілька ядер, наприклад). Якщо 'b' є фазою 'сортування', то це не застосовуватиметься - 'b' повинно побачити весь його вхід, перш ніж він зможе генерувати будь-який свій вихід.
Якщо ви хочете виявити, які команди (и) не вдається, ви можете використовувати:
(./a || echo "./a exited with $?" 1>&2) |
(./b || echo "./b exited with $?" 1>&2) |
(./c || echo "./c exited with $?" 1>&2)
Це просто і симетрично - тривіально поширюватися на 4-частинний або N-частинний трубопровід.
Прості експерименти з «set -e» не допомогли.
&&|
що означало б "продовжувати трубу лише у тому випадку, коли попередня команда була успішною". Я припускаю, що ви також можете мати,|||
що означатиме "продовжувати трубу, якщо попередня команда не вдалася" (і, можливо, передавати повідомлення про помилку, як Bash 4|&
).