Mengapa cURL mengembalikan kesalahan “(23) Gagal menulis”?

153

Ini berfungsi ok sebagai alat tunggal:

curl "someURL"
curl -o - "someURL"

tapi itu tidak bekerja di saluran pipa:

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

mengembalikan:

(23) Failed writing body

Apa masalah dengan piping output CURL? Bagaimana cara buffer seluruh output CURL dan kemudian menanganinya?

statis
sumber
1
Bagi saya ini berfungsi, tidak perlu buffer.
hek2mgl
1
apakah ini juga berfungsi dalam pipeline ?:curl 'http://www.multitran.ru/c/m.exe?CL=1&s=hello&l1=1' | tr -d '\n'
static
1
Menambahkan tag osx. Sayangnya saya tidak dapat membantu dengan ini. Saya menggunakan Linux
hek2mgl
1
masalahnya adalah penyandian halaman (cyrilic, win-1251). Jadi saya harus menggunakaniconv -f ...
statis
5
Sama seperti petunjuk lain: Tambang gagal, karena disk penuh.
Vince Varga

Jawaban:

113

Ini terjadi ketika program yang disalurkan (misalnya grep) menutup pipa baca sebelum program sebelumnya selesai menulis seluruh halaman.

Di curl "url" | grep -qs foo, segera setelah grep memiliki apa yang diinginkannya, ia akan menutup aliran baca dari curl. cURL tidak mengharapkan ini dan memancarkan kesalahan "Failed writing body".

Solusinya adalah menyalurkan aliran melalui program perantara yang selalu membaca seluruh halaman sebelum memasukkannya ke program berikutnya.

Misalnya

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

tacadalah program Unix sederhana yang membaca seluruh halaman input dan membalik urutan baris (karenanya kami menjalankannya dua kali). Karena harus membaca seluruh input untuk menemukan baris terakhir, itu tidak akan menampilkan apa pun untuk grep sampai cURL selesai. Grep masih akan menutup aliran baca ketika memiliki apa yang dicari, tetapi hanya akan memengaruhi tac, yang tidak memunculkan kesalahan.

Kaworu
sumber
5
Tidak bisakah Anda menyalurkan melalui pipa catsekali saja? Setidaknya, selesaikan masalah ini untuk saya.
benvd
5
Tidak. Mungkin membantu dengan dokumen kecil tetapi ketika terlalu besar untuk muat di buffer cat menggunakan kesalahan akan muncul kembali. Anda bisa menggunakan -suntuk membungkam semua pesan kesalahan (dan kemajuan) jika Anda tidak membutuhkannya.
Kaworu
9
tac|tacmengubah input jika input tidak diakhiri dengan linefeed, atau misalnya printf a\\nb\\nc|tac|tacmencetak di a\ncbmana \nlinefeed. Anda bisa menggunakannya sponge /dev/stdout. Pilihan lain adalah printf %s\\n "$(cat)", tetapi ketika input berisi byte kosong di shell selain Zsh, yang melewatkan byte nol atau berhenti membaca setelah byte nol pertama.
nisetama
Dari dokumen: CURLE_WRITE_ERROR (23) Terjadi kesalahan saat menulis data yang diterima ke file lokal, atau kesalahan dikembalikan ke libcurl dari callback tulis. curl.haxx.se/libcurl/c/libcurl-errors.html
Jordan Stewart
3
Ini harus diterima jawaban karena menjelaskan masalah, karena itu tidak memberikan solusi yang mampu karena tidak ada tacperintah pada macOS
Dominik Bucher
49

Untuk kelengkapan dan pencarian di masa mendatang:

Ini masalah bagaimana CURL mengelola buffer, buffer menonaktifkan aliran output dengan opsi -N.

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

pengguna5968839
sumber
8
Itu berhasil curl -s https://raw.githubusercontent.com/hermitdave/FrequencyWords/master/content/2016/ro/ro_50k.txt | head -20(tanpa -ssaya mendapatkan kesalahan yang sama).
Dan Dascalescu
24

Kemungkinan lain, jika menggunakan opsi -o(file output) - direktori tujuan tidak ada.

misalnya. jika sudah -o /tmp/download/abc.txtdan / tmp / unduh tidak ada.

Oleh karena itu, pastikan direktori yang diperlukan dibuat / ada sebelumnya, gunakan --create-dirsopsi dan - ojika perlu

MikeW
sumber
2
Terima kasih, --create-dirs memecahkan masalah ini untuk saya dalam situasi yang paling tidak biasa, tidak pernah tahu apa yang salah, tapi ini tiketnya!
rfay
1
Itu terjadi pada saya dalam kasus yang sama. Saya lupa mendeklarasikan variabel $ out untuk output. Terima kasih, Mike.
Mincong Huang
8

Jadi itu masalah pengkodean. Iconv memecahkan masalah

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

Anda dapat melakukan ini alih-alih menggunakan -oopsi:

curl [url] > [file]


sumber
jadi, tidak menggunakan pipa dan malah melakukan semua pekerjaan atas sistem file? Saya ingin menggunakan hasil curl dengan pipa.
statis
6

Saya memiliki kesalahan yang sama tetapi dari alasan berbeda. Dalam kasus saya, saya memiliki (tmpfs) partisi dengan hanya 1GB ruang dan saya mengunduh file besar yang akhirnya mengisi semua memori pada partisi itu dan saya mendapatkan kesalahan yang sama seperti Anda.

LLL
sumber
5

Server kehabisan ruang disk, dalam kasus saya.

Periksa dengan df -k .

Saya diberitahu tentang kurangnya ruang disk ketika saya mencoba memipakan tacdua kali, seperti yang dijelaskan dalam salah satu jawaban lain: https://stackoverflow.com/a/28879552/336694 . Itu menunjukkan kepada saya pesan kesalahan write error: No space left on device.

HostedMetrics.com
sumber
Saya menerima kesalahan yang sama karena kehabisan ruang disk di dalam sebuah wadah, karena siapa pun yang memukul masalah yang sama dapat membersihkan ruang di dalam wadah mereka dengandocker system prune
Dave
2

Saya menemukan pesan kesalahan ini ketika mencoba menginstal varnish cache di ubuntu. Pencarian google mendaratkan saya di sini untuk kesalahan (23) Failed writing body, maka memposting solusi yang bekerja untuk saya.

Bug ini ditemui saat menjalankan perintah sebagai root curl -L https://packagecloud.io/varnishcache/varnish5/gpgkey | apt-key add -

solusinya adalah berjalan apt-key addsebagai non root

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

Jika Anda mencoba sesuatu yang mirip seperti source <( curl -sS $url )dan mendapatkan (23) Failed writing bodykesalahan, itu karena sumber substitusi proses tidak berfungsi bash 3.2(default untuk macOS).

Sebagai gantinya, Anda dapat menggunakan solusi ini.

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

Bagi saya, itu masalah izin. Docker run disebut dengan profil pengguna tetapi root adalah pengguna di dalam wadah. Solusinya adalah membuat curl write ke / tmp karena itu memiliki izin menulis untuk semua pengguna, bukan hanya root.

Saya menggunakan opsi -o.

-o / tmp / file_to_download

lallolu
sumber
-1

Di Bash dan zsh (dan mungkin cangkang lain), Anda bisa menggunakan subtitusi proses ( Bash / zsh ) untuk membuat file dengan cepat, dan kemudian menggunakannya sebagai input untuk proses selanjutnya dalam rantai pipa.

Sebagai contoh, saya mencoba mengurai output JSON dari cURL menggunakan jqdan less, tetapi mendapatkan Failed writing bodykesalahan.

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

Ketika saya menulis ulang menggunakan proses substitusi, itu berhasil!

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

Catatan: jqmenggunakan argumen ke-2 untuk menentukan file input

Bonus: Jika Anda menggunakan jqseperti saya dan ingin menjaga output berwarna di less, gunakan baris perintah berikut ini sebagai gantinya:

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

(Terima kasih kepada Kowaru untuk penjelasan mereka tentang mengapa Failed writing body itu terjadi. Namun, solusi mereka menggunakan tacdua kali tidak bekerja untuk saya. Saya juga ingin menemukan solusi yang dapat meningkatkan skala untuk file besar dan mencoba untuk menghindari masalah lain yang dicatat sebagai komentar untuk jawaban itu.)

Robert
sumber