31

Я недавно переустановил RVM (следуя инструкциям на http://rvm.io) после новой установки Ubuntu 12.10, когда я получил SSD Drive.

Теперь, когда я печатаю : type rvm | head -1

Я получаю следующую ошибку:

rvm is a function
-bash: type: write error: Broken pipe

Но если я немедленно повторю команду, то получу только:

rvm is a function

И, кажется, все в порядке? Что происходит? Что я могу сделать, чтобы это исправить? Так не бывает всегда. Это кажется более спорадическим. Я пытался найти какую-то модель, но пока не нашел.

3 ответа3

53

Видеть "Сломанную трубу" в этой ситуации редко, но нормально.

Когда вы запускаете, type rvm | head -1 , bash выполняет type rvm в одном процессе, head -1 в другом. 1 Stdout type подключается к концу "write" канала , а stdin head к концу "read". Оба процесса выполняются одновременно.

Процесс 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 .

23

Вы можете исправить сломанную трубу за счет другого процесса , вставив tail -n +1 в свою трубу, например:

типа рвм | хвост -n +1 | голова -1

+1 говорит tail напечатать первую строку ввода и все, что следует. Вывод будет точно таким же, как если бы tail -n +1 там не было, но программа достаточно умна, чтобы проверить стандартный вывод и аккуратно закрыть канал. Нет больше сломанных труб.

2

write error: Broken pipe сообщение « Сломанный канал» относится к процессу записи, который пытается записать в канал без читателей на конце чтения этого канала, а также в особых случаях, когда сигнал SIGPIPE игнорируется текущим или родительским объектом. процесс. Если родительский процесс установил игнорирование SIGPIPE дочерний процесс не сможет отменить это снова в неинтерактивной оболочке.

Однако возможно уничтожить type rvm когда заголовок head -1 завершается с использованием явных подоболочек. Таким образом, мы можем создать фоновый type rvm , отправить typepid в подоболочку head -1 а затем реализовать ловушку для EXIT для явного уничтожения type rvm .

trap "" PIPE        # parent process sets SIGPIPE to be ignored
bash                # start child process
export LANG=C
# create a fake rvm function
eval "
rvm() {
$(printf 'echo line of rvm code %s\n' {1..10000})
}
"

# rvm is a function
# bash: type: write error: Broken pipe
type rvm | head -1

# kill type rvm when head -1 terminates
# sleep 0: do nothing but with external command
( (sleep 0; type rvm) & echo ${!} ; wait ${!} ) | 
    (trap 'trap - EXIT; kill "$typepid"; exit' EXIT; typepid="$(head -1)"; head -1)

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .