깨진 파이프 오류를 어떻게 해결합니까?


36

SSD 드라이브를 얻었을 때 Ubuntu 12.10을 새로 설치 한 후 최근에 RVM을 다시 설치했습니다 ( http://rvm.io 의 지침에 따름 ).

이제 내가 입력하면 : type rvm | head -1

다음과 같은 오류가 발생합니다.

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

그러나 명령을 즉시 반복하면 다음과 같은 내용 만 수신됩니다.

rvm is a function

그리고 모든 것이 괜찮은 것처럼 보입니까? 무슨 일이야? 이 문제를 해결하려면 어떻게해야합니까? 항상 그런 것은 아닙니다. 더 산발적으로 보입니다. 나는 그것에 어떤 종류의 패턴을 찾으려고 노력했지만 아직하지 않았습니다.

답변:


57

이 상황에서 "깨진 파이프"를 보는 것은 드물지만 정상입니다.

을 실행 type rvm | head -1하면 bash type rvm는 한 프로세스 head -1에서 다른 프로세스로 실행 됩니다 . 1 의 표준 출력은 파이프type 의 "쓰기"말단에 연결되어 있으며, " 표준 "은 "읽기"말단에 연결되어 있습니다. 두 프로세스가 동시에 실행됩니다.head

head -1프로세스는 stdin (일반적으로 8kB 청크 단위)에서 데이터를 읽고 단일 라인을 인쇄하고 ( -1옵션 에 따라 ) 종료하여 파이프의 "읽기"끝이 닫힙니다. rvm함수가 상당히 길기 때문에 (bash에서 파싱하고 재구성 한 후 약 11kB), 이는 여전히 몇 kB의 데이터를 쓸 때 head종료 한다는 것을 의미합니다 type.

이 시점에서, type다른 쪽 끝이 닫힌 파이프 ( 부러진 파이프)에 쓰려고 시도하기 때문에이 파이프가 쓴 write () 함수는 "깨진 파이프"로 변환 된 EPIPE 오류를 반환합니다. 이 오류 외에도 커널은 SIGPIPE 신호를로 보내면 type기본적으로 프로세스가 즉시 종료됩니다.

(대부분의 사용자는 첫 번째 프로세스가 계속 실행되고 아무데도 쓰려고하지 않기 때문에이 신호는 대화식 쉘에서 매우 유용합니다. 한편 비 대화식 서비스는 SIGPIPE를 무시합니다. 장기 실행 데몬에는 좋지 않습니다. 그런 간단한 오류로 죽어라. 그래서 그들은 오류 코드가 매우 유용하다는 것을 알게된다.)

그러나 신호 전달은 즉시 100 %가 아니며 write ()가 EPIPE를 반환하고 신호를 받기 전에 잠시 동안 프로세스가 계속 실행되는 경우가있을 수 있습니다. 이 경우 typeSIGPIPE에 의해 종료되기 전에 쓰기 실패를 확인하고 오류 코드를 변환하며 오류 메시지를 stderr로 인쇄 할 수있는 충분한 시간을 얻습니다. (오류 메시지에는 "-bash : type :"이라고 표시되어 있기 때문에 typebash 자체의 기본 제공 명령입니다.)

type프로세스와 커널의 신호 전달 코드가 문자 그대로 동시에 다른 코어에서 실행될 수 있기 때문에 이것은 다중 CPU 시스템에서 더 일반적으로 보입니다 .

typewrite () 함수로부터 EPIPE를 수신 할 때 즉시 종료 되도록 내장 (bash의 소스 코드에서)을 패치하여이 메시지를 제거 할 수 있습니다 .

그러나 걱정할 필요는 없으며 rvm어떤 식 으로든 설치 와 관련이 없습니다 .


고맙습니다! 나는 그것에 대해 걱정했다. 나는 어제 밤에 rvm 설치 문제를 해결하고 그것을 고치려고 고치기 위해 약 1 시간 정도 인터넷 검색을했습니다. 방금 SSD 드라이브로 교체하고 LVM을 사용하고 하드 드라이브를 암호화하여 많은 변수가 작동하고 있었으며 어떤 일이 발생했는지 확실하지 않았습니다. 마음을 편안하게 해주셔서 감사합니다!
Jason Shultz

나는의 출력 파이프 된 ls스루 head -1년 동안, 오늘은 내가 깨진 파이프 메시지를 받고 있어요.
Tulains Córdova

1
(참고 : "Broken pipe"오류는 신호에서 발생하지 않습니다.이 오류는 errno 에서 발생합니다 . 쉘은 신호 유도 종료에 대한 문자 메시지를 표시 할 수 있지만 일반적으로 SIGPIPE 종료는 '
clean'one

23

파이프 에 다음tail -n +1 과 같이 삽입 하면 다른 프로세스희생하면서 파손 된 파이프 수정할 수 있습니다 .

rvm 유형 | 꼬리 -n +1 | 머리 -1

+1말한다 tail입력 및 다음 모든 것의 첫 번째 줄을 인쇄 할 수 있습니다. 출력은 tail -n +1존재하지 않는 것과 정확히 동일 하지만 프로그램은 표준 출력을 확인하고 파이프를 깨끗하게 닫을만큼 영리합니다. 더 이상 파이프가 파손 되지 않습니다 .


1
좋은 트릭. 여기에 제공된 것과 다른 상황에서 사용했습니다. 감사!
누군가 아직도 당신을 사용합니다 MS-DOS

6
훌륭한 솔루션처럼 보였지만 꼬리 8.21이있는 Ubuntu 14.04.2에서 "꼬리 : 쓰기 오류 : 깨진 파이프"가 표시되어 개선되지 않았습니다.
Roger Dueck

2
@RogerDueck이 정확합니다. 또한 Mandriva 시스템에서도 이와 비슷한 문제가 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가 수정됩니다.
Andrew Beals

3
나는 xargs 또는 type이 SIGPIPE에 대해 kvetching해야한다고 생각하지 않지만 내 제안을 더 수정 할 것입니다. type rvm | (head -1 ; dd of=/dev/null) 이것은 물론 : 모든 입력이 처리되도록하는 다른 제안과 유사합니다. 그러나 dd이러한 것들을 처리 할 수있는 가장 효율적인 프로그램이어야합니다.
Andrew Beals


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)

grawity의 답변에서 : type실패한 쓰기를 알기에 충분한 시간을 얻습니다. 오류 코드를 변환하고 SIGPIPE에 의해 종료되기 전에 오류 메시지를 stderr에 인쇄하십시오 . 귀하의 솔루션으로 생산자 프로세스 ( type여기)가 실패한 쓰기 (닫힌 파이프로 인해)에 반응하는 것을 막지 못한다고 생각 합니까?
Piotr Dobrogost
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.