В документации по bash в разделе говорится о трубопроводах :
Каждая команда в конвейере выполняется в своей собственной оболочке [...]
«В своей собственной оболочке» означает, что создается новый процесс bash, который затем выполняет фактическую команду. Каждый подоболочек запускается успешно, даже если он сразу определяет, что команда, которую он просит выполнить, не существует.
Это объясняет, почему весь канал может быть успешно настроен, даже если одна из команд является бессмысленной. Bash не проверяет, может ли каждая команда быть запущена, он передает ее в подоболочки. Это также объясняет, почему, например, команда nonexisting-command | touch hello
выдаст ошибку «команда не найдена», но файл hello
будет создан.
В том же разделе также написано:
Оболочка ожидает завершения всех команд в конвейере, прежде чем вернуть значение.
В sleep 5 | nonexisting-command
, как указывал А.Х., sleep 5
завершается через 5 секунд, а не сразу, поэтому оболочка также будет ждать 5 секунд.
Я не знаю, почему реализация была сделана таким образом. В таких случаях, как ваш, поведение определенно не такое, как можно было бы ожидать.
В любом случае, один немного уродливый способ - использовать FIFO:
mkfifo myfifo
./long-running-script.sh > myfifo &
whoops-a-typo < myfifo
Здесь запускается long-running-script.sh
, а затем сценарии сразу выходят из строя на следующей строке. Используя несколько FIFO, это можно распространить на каналы с более чем двумя командами.