Broken Pipeエラーを修正するにはどうすればよいですか?


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 rvm1つのプロセスで実行されhead -1、別のプロセスで実行されます。1のstdoutはパイプのtype "write"端に接続され、stdinは"read"端に接続されます。両方のプロセスが同時に実行されます。head

head -1プロセスは、(通常8キロバイトのチャンクに)標準入力からデータを読み出し、単一の(に係る線プリントアウト-1クローズする管の端部を「読み取り」引き起こし、オプション)、および終了し。以来rvm関数非常に長い(構文解析およびBashによって再構築された後、約11 KB)、このことは意味head出口はながらtype依然として書き出すデータの数KBを有しています。

この時点で、typeもう一方の端が閉じられているパイプ(破損したパイプ)に書き込みを試行しているため、それが調整したwrite()関数はEPIPEエラーを返します。このエラーに加えて、カーネルはSIGPIPEシグナルもに送信typeします。これはデフォルトでプロセスをすぐに強制終了します。

(シグナルは、ほとんどのユーザーが最初のプロセスを実行し続けてどこにも書き込もうとしないため、対話型シェルで非常に役立ちます。一方、非対話型サービスはSIGPIPEを無視します。そのような単純なエラーで死にます-そのため、エラーコードは非常に便利です。)

ただし、シグナルの配信は100%即時ではなく、write()がEPIPEを返し、シグナルを受信する前にしばらくの間プロセスが実行し続ける場合があります。この場合、type SIGPIPEによって強制終了される前に、書き込みの失敗を通知し、エラーコードを変換し、エラーメッセージをstderrに出力するのに十分な時間を確保します。(typebash自体の組み込みコマンドであるため、エラーメッセージには「-bash:type:」と表示されます。)

これは、typeプロセスとカーネルのシグナル配信コードが異なるコアで文字通り同時に実行できるため、マルチCPUシステムではより一般的であるようです。

type組み込み(bashのソースコード内)にパッチを適用して、write()関数からEPIPEを受信するとすぐに終了するようにすることで、このメッセージを削除することができます。

ただし、心配する必要はありませんrvm。インストールとはまったく関係ありません。


ありがとうございました!私はそれが心配でした。昨夜、rvmのインストールのトラブルシューティングを行い、それを修正するために修復を行って、約1時間のグーグル検索を行いました。SSDドライブと交換してLVMを使用し、ハードドライブを暗号化したので、多くの変数が作用し、横になった可能性があるかどうかわかりませんでした。安心してくれてありがとう!
ジェイソンシュルツ

私はの出力パイピングされているlsスルーをhead -1年間にわたり、そして今日は壊れたパイプのメッセージを取得しています。
Tulainsコルドバ

1
(注:「壊れたパイプ」エラーはシグナルから発生するものではありません。errnoから発生します。 「クリーン」なもの。)
荒廃

23

次のようにパイプに挿入することで、別のプロセスを犠牲にして破損したパイプ修正できますtail -n +1

タイプrvm | tail -n +1 | 頭-1

+1伝えtail入力して、次のすべての最初の行を印刷します。出力はtail -n +1、存在しなかった場合とまったく同じになりますが、プログラムは標準出力をチェックするのに十分スマートであり、パイプをきれいに閉じます。これ以上壊れたパイプはありません。


1
ナイストリック。ここで提供されている状況とは異なる状況で使用しました。ありがとう!
誰かがまだあなたを使用していますMS-DOS

6
すばらしいソリューションのように見えましたが、テール8.21のUbuntu 14.04.2では、「テール:書き込みエラー:パイプが壊れています」と表示されますが、これは改善されていません。
ロジャーデュック

2
@RogerDueckは正しいです。同様の問題がfind /var/lib/mysql -xdev -type f -daystart -mmin +5 -print0 | xargs -0 ls -ldt | tail -n +1 | head確実に生じるため、Mandrivaシステムでもこれを確認できますxargs: ls: terminated by signal 13。知っているように、問題は入力の枯渇の1つであり、実際にはバッファリングを処理するコマンドが1つしかありません。ddです。| dd obs=1Mパイプラインに追加すると、ユースケースのSIGPIPEが修正されます。
アンドリュービールズ

3
私は提案をさらに修正しますが、xargsまたはtypeがSIGPIPEについてkvetchingする必要があるとは思わないことに注意しますが、type rvm | (head -1 ; dd of=/dev/null) これにはもちろん、すべての入力が処理されるため、これは他の提案と似ています、しかしdd、そのようなことを処理するための最も効率的なプログラムでなければなりません。
アンドリュービールズ

3
SIGPIPE違反者に関する解説はこちら:mail-index.netbsd.org/tech-userlevel/2013/01/07/msg007110.html
Andrew Beals

2

write error: Broken pipeメッセージがない読者とパイプへの書き込みしようとし、そのパイプのリーディング端とその特別な状況に残した書き込みプロセスを指すSIGPIPE信号は、電流または親プロセスのいずれかによって無視されるように設定されています。設定した親プロセスだった場合SIGPIPE無視するようにているのがある場合、子プロセスは非対話型シェルで再度元に戻すことはできません。

ただし、明示的なサブシェルを使用してtype rvmhead -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's answer:typeSIGPIPEによって殺される前に、失敗した書き込みに気づき、エラーコードを変換し、エラーメッセージを標準エラー出力に出力するのに十分な時間を取得します。あなたの解決策は、プロデューサープロセス(typeここ)が(閉じたパイプのために)失敗した書き込みに反応することを妨げないと思いますか?
ピョートルドブロゴスト16
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.