Видеть «Сломанную трубу» в этой ситуации редко, но нормально.
Когда вы запускаете type rvm | head -1
, bash выполняется type rvm
в одном процессе, head -1
в другом. 1 стандартный вывод из type
подключен к «записи» конец трубы , то из стандартного ввода head
к «читать» конец. Оба процесса выполняются одновременно.
head -1
Процесс считывает данные из стандартного ввода (обычно в куски 8 КБ), вывести в одной строке ( в соответствии с -1
параметром), и выходы, в результате чего «читать» конец трубы должен быть закрыт. Поскольку rvm
функция довольно длинная (около 11 кБ после анализа и восстановления bash), это означает, что head
при выходе type
все еще остается несколько кБ данных для записи.
На этом этапе, поскольку type
он пытается выполнить запись в канал, чей другой конец был закрыт - сломанный канал, - функция write (), которую он вызвал, вернет ошибку EPIPE, переведенную как «Broken pipe». В дополнение к этой ошибке ядро также отправляет сигнал SIGPIPE type
, который по умолчанию немедленно завершает процесс.
(Сигнал очень полезен в интерактивных оболочках, так как большинство пользователей не хотят, чтобы первый процесс продолжал выполняться и пытался писать в никуда. Между тем, неинтерактивные службы игнорируют SIGPIPE - это не будет хорошо для долго работающего демона, чтобы умереть от такой простой ошибки - поэтому они находят код ошибки очень полезным.)
Однако доставка сигнала не происходит на 100% немедленно, и могут быть случаи, когда write () возвращает EPIPE, и процесс продолжает работать некоторое время до получения сигнала. В этом случае у вас type
будет достаточно времени, чтобы заметить неудачную запись, перевести код ошибки и даже напечатать сообщение об ошибке в stderr, прежде чем SIGPIPE прекратит его. (В сообщении об ошибке указано «-bash: type:», поскольку type
это встроенная команда самого bash.)
Похоже, что это чаще встречается в многопроцессорных системах, поскольку type
процесс и код доставки сигнала ядра могут работать на разных ядрах, буквально одновременно.
Можно было бы удалить это сообщение, исправив type
встроенную функцию (в исходном коде bash) для немедленного выхода при получении EPIPE от функции write ().
Тем не менее, это не о чем беспокоиться, и это никак не связано с вашей rvm
установкой.
ls
черезhead -1
, и сегодня я получаю сообщение о сломанной трубе.Вы можете исправить сломанную трубу за счет другого процесса , вставив
tail -n +1
в свою трубу, например так:+1
Говоритtail
напечатать первую строку ввода , и все , что следует. Вывод будет точно таким же, как если быtail -n +1
его не было, но программа достаточно умна, чтобы проверить стандартный вывод, и полностью закрывает канал. Нет больше сломанных труб .источник
find /var/lib/mysql -xdev -type f -daystart -mmin +5 -print0 | xargs -0 ls -ldt | tail -n +1 | head
надежно доходностиxargs: ls: terminated by signal 13
. Как мы знаем, проблема заключается в исчерпании ввода, и на самом деле только одна команда имеет дело с буферизацией: dd. Добавление| dd obs=1M
в конвейер исправляет SIGPIPE для моего варианта использования.type rvm | (head -1 ; dd of=/dev/null)
это, конечно, похоже на другие предложения, поскольку вызывает обработку всего ввода , ноdd
должна быть самой эффективной программой для обработки таких вещей.write error: Broken pipe
Сообщение относится к процессу письма , который пытается записать в трубу без каких - либо читателей , оставленных на конце чтения этой трубы и специального обстоятельство , чтоSIGPIPE
сигнал установлен быть проигнорированы либо током или родительского процессом. Если это был родительский процесс, которыйSIGPIPE
был проигнорирован, то дочерний процесс не может отменить это снова в неинтерактивной оболочке.Тем не менее, можно завершить,
type rvm
когдаhead -1
завершается с помощью явных подоболочек. Таким образом, мы можем выполнить фонtype rvm
, отправитьtypepid
вhead -1
подоболочку, а затем реализовать ловушкуEXIT
дляtype rvm
явного уничтожения .источник
type
получает достаточно времени, чтобы заметить неудачную запись, перевести код ошибки и даже напечатать сообщение об ошибке в stderr перед тем, как SIGPIPE уничтожит его . Я думаю, что ваше решение не мешает процессу производителя (type
здесь) реагировать на неудачную запись (из-за закрытого канала), не так ли?