Какова политика завершения конвейерной программы в bash?

Когда завершается конвейерная программа и кто контролирует этот процесс завершения? Я прочитал Bash: почему канал прерывается?, но он охватывает это вопрос только частично. Попытавшись самостоятельно ответить на этот вопрос, я сделал пару примеров, чтобы увидеть их результаты. А вот этого я не понимаю: (a.sh):

#!/bin/bash

echoerr() { echo $@ 1>&2; }

echoerr a.sh started

sleep 1
echo 1

sleep 1
echo 2

sleep 1
echo 3

sleep 1 # Line 1
echo 4  # Line 2

echoerr a.sh finished

И я запускаю его как ./a.sh | head -3. Результат:

a.sh started
1
2
3

Из вывода я понял, что ./a.sh был завершен сигналом SIGPIPE после чтения первых 3 строк ввода, потому что больше данных не требовалось. Но когда я удаляю либо строку 1 либо строку 2, вывод меняется на следующее:

a.sh started
1
2
3
a.sh finished

Итак, мой вопрос:

  • Какова политика завершения конвейерной программы?
  • Почему строка 1 влияет на поведение программы?
  • Почему строка 2 влияет на поведение программы?

person sasha.sochka    schedule 28.07.2013    source источник


Ответы (1)


Как вы сказали, ваш сценарий оболочки умрет, если он попытается записать в закрытый канал. Не будет, если не будет.

Если вы удалите вторую строку, a.sh не будет пытаться писать в свою stdout после echo 3, поэтому у нее нет причин сбоя.

Удаление первой строки может не дать вам одинаковый результат при каждом запуске теста. Есть проблема со временем. Если последние два оператора echo обрабатываются до того, как head попытается прочитать из своего ввода (и завершится, потому что он достиг 3 строк), тогда a.sh не получит ошибку сломанного конвейера. Если синхронизация такова, что head выполняет чтение между двумя echo, то a.sh получит ошибку конвейера и умрет.

person Mat    schedule 28.07.2013