cURLがエラー「(23)書き込みに失敗しました」を返すのはなぜですか?


152

それは単一のツールとして問題なく動作します:

curl "someURL"
curl -o - "someURL"

ただし、パイプラインでは機能しません。

curl "someURL" | tr -d '\n'
curl -o - "someURL" | tr -d '\n'

それは返します:

(23) Failed writing body

cURL出力のパイプ処理の問題は何ですか?cURL出力全体をバッファリングしてから処理する方法は?


1
私にとってそれは機能し、バッファする必要はありません。
hek2mgl 2013年

1
この作品はあまりにもパイプラインでない?:curl 'http://www.multitran.ru/c/m.exe?CL=1&s=hello&l1=1' | tr -d '\n'
静的

1
osxタグを追加しました。残念ながら私はこれを手伝うことはできません。私はLinuxを使用しています
hek2mgl 2013年

1
問題はページのエンコードでした(cyrilic、win-1251)。したがって、使用する必要がありますiconv -f ...
静的な

5
もう1つのヒントとして:ディスクがいっぱいだったため、鉱山は失敗しました。
Vince Varga 2016年

回答:


113

これは、前のプログラムがページ全体の書き込みを完了する前に、パイププログラム(grepなど)が読み取りパイプを閉じたときに発生します。

ではcurl "url" | grep -qs foo、grepが必要なものを取得するとすぐに、curlからの読み取りストリームを閉じます。cURLはこれを予期せず、「Failed writing body」エラーを発行します。

回避策は、次のプログラムにフィードする前に常にページ全体を読み取る中間プログラムにストリームをパイプすることです。

例えば

curl "url" | tac | tac | grep -qs foo

tac入力ページ全体を読み取り、行の順序を逆にする単純なUnixプログラムです(したがって、2回実行します)。入力全体を読み取って最後の行を見つける必要があるため、cURLが完了するまで、grepには何も出力されません。Grepは、探しているものがある場合でも読み取りストリームを閉じますが、tacにのみ影響し、エラーは発生しません。


5
単純にcat一度だけパイプで通してくれませんか?少なくとも私にとっては問題を解決します。
benvd 2016年

5
いいえ。小さいドキュメントには役立ちますが、バッファに収まらないほど大きい場合、猫はエラーを再-s表示します。不要な場合は、すべてのエラーメッセージ(および進行状況)を消音するために使用できます。
Kaworu

9
tac|tac入力は改行で終わる、または例えばのためにない場合は、入力を変更printf a\\nb\\nc|tac|tac印刷改行です。代わりに使用できます。別のオプションはですが、Zsh以外のシェルで入力にnullバイトが含まれている場合、nullバイトをスキップするか、最初のnullバイトの後に読み取りを停止します。a\ncb\nsponge /dev/stdoutprintf %s\\n "$(cat)"
nisetama 2016

ドキュメントから:CURLE_WRITE_ERROR(23)受信したデータをローカルファイルに書き込むときにエラーが発生したか、書き込みコールバックからlibcurlにエラーが返されました。curl.haxx.se/libcurl/c/libcurl-errors.html
ジョーダンスチュワート

3
これは問題を説明しているため、受け入れられるべき回答です。ただしtac、macOS にはコマンドがないため、有効なソリューションは提供されません
Dominik Bucher

48

完全性と将来の検索:

それはcURLがバッファーを管理する方法の問題です。バッファーは-Nオプションで出力ストリームを無効にします。

例: curl -s -N "URL" | grep -q Welcome


8
それはうまくいきましたcurl -s https://raw.githubusercontent.com/hermitdave/FrequencyWords/master/content/2016/ro/ro_50k.txt | head -20-s同じエラーが出ることはありません)。
Dan Dascalescu 2017

24

別の可能性、使用する場合 -o(出力ファイル)オプション -宛先ディレクトリーが存在しません。

例えば。あり-o /tmp/download/abc.txt、/ tmp / downloadが存在しない場合。

したがって、必要なディレクトリが事前に作成/存在していることを確認し、--create-dirsオプションと同様に- o必要に応じて使用してください


2
おかげで、--create-dirsは、最も異常な状況で私のためにこれを解決しましたが、何が間違っているのか理解できませんでしたが、これがチケットでした!
rfay

1
それは同じようなケースで私に起こりました。出力用に変数$ outを宣言するのを忘れました。ありがとう、マイク。
Mincong Huang

8

つまり、エンコードの問題でした。Iconvは問題を解決します

curl 'http://www.multitran.ru/c/m.exe?CL=1&s=hello&l1=1' | iconv -f windows-1251 | tr -dc '[:print:]' | ...

8

-oオプションを使用する代わりにこれを行うことができます:

curl [url] > [file]


では、パイプを使用せずに、すべての作業をファイルシステムで実行しますか?パイプでカールの出力を使用したいと思いました。
静的

6

同じエラーが発生しましたが、理由は異なります。私の場合、(tmpfs)パーティションに1GBのスペースしかなく、大きなファイルをダウンロードしていたため、最終的にそのパーティションのすべてのメモリいっぱいになり、あなたと同じエラーが発生しました。


5

私の場合、サーバーのディスク容量が不足しています。

それをチェックする df -k .

tac他の回答の1つであるhttps://stackoverflow.com/a/28879552/336694で説明されているように、パイプラインを2回試行したときに、ディスク領域の不足が警告されました。エラーメッセージが表示されましたwrite error: No space left on device


コンテナ内のディスク領域が不足しているために同じエラーが発生しました。同じ問題にdocker system prune
Dave

2

Ubuntuにワニスキャッシュをインストールしようとしたときに、このエラーメッセージが表示されました。グーグル検索はエラーのために私をここに導きました(23) Failed writing body、それゆえ私のために働いた解決策を投稿しました。

rootとしてコマンドを実行中にバグが発生します curl -L https://packagecloud.io/varnishcache/varnish5/gpgkey | apt-key add -

解決策はapt-key add非ルートとして実行することです

curl -L https://packagecloud.io/varnishcache/varnish5/gpgkey | apt-key add -

1

同様のことを試みsource <( curl -sS $url )(23) Failed writing bodyエラーが発生するのは、プロセス置換のソースが機能しないためですbash 3.2ためです(macOSのデフォルト)。

代わりに、この回避策を使用できます。

source /dev/stdin <<<"$( curl -sS $url )"

0

私にとっては、許可の問題でした。Docker runはユーザープロファイルで呼び出されますが、rootはコンテナー内のユーザーです。解決策は、rootだけでなく、すべてのユーザーに書き込み権限があるため、curlに/ tmpへの書き込みを行わせることでした。

-oオプションを使用しました。

-o / tmp / file_to_download


-1

Bashとzsh(およびおそらく他のシェル)では、プロセス置換(Bash / zsh)を使用してファイルをその場で作成し、それをパイプラインチェーンの次のプロセスへの入力として使用できます。

たとえば、jqおよびを使用してcURLからのJSON出力を解析しようとしましlessたが、Failed writing bodyエラーが発生していました。

# Note: this does NOT work
curl https://gitlab.com/api/v4/projects/ | jq | less

プロセス置換を使用して書き直したところ、うまくいきました!

# this works!
jq "" <(curl https://gitlab.com/api/v4/projects/) | less

注:jq2番目の引数を使用して入力ファイルを指定します

おまけ:jq私のように使用していて、カラー化された出力をに保持したい場合less、代わりに次のコマンドラインを使用します。

jq -C "" <(curl https://gitlab.com/api/v4/projects/) | less -r

理由が説明されたKowaruに感謝します。ただし、2回使用するという解決策は私にはうまくいきませんでした。また、大きなファイルに対してより適切にスケーリングし、コメントとして記載されている他の問題を回避しようとする解決策を見つけたかったその答えに。) Failed writing bodytac

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.