Neden cURL dönüş hatası “(23) Yazı yazma hatası”?


153

Tamam tek bir araç olarak çalışır:

curl "someURL"
curl -o - "someURL"

ancak bir boru hattında çalışmaz:

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

döndürür:

(23) Failed writing body

CURL çıkışının borulanması ile ilgili sorun nedir? Tüm cURL çıktısını nasıl arabelleğe alır ve daha sonra nasıl işlerim?


1
Benim için çalışıyor, tamponlamaya gerek yok.
hek2mgl

1
Bu boru hattında da işe yarıyor mu ?:curl 'http://www.multitran.ru/c/m.exe?CL=1&s=hello&l1=1' | tr -d '\n'
statik

1
Osx etiketleri eklendi. Ne yazık ki bu konuda yardım edemem. Linux kullanıyorum
hek2mgl

1
sorun sayfanın kodlanmasıydı (cyrilic, win-1251). Bu yüzden kullanmalıyımiconv -f ...
statik

5
Başka bir ipucu gibi: Benimki başarısız oldu, çünkü disk doluydu.
Vince Varga

Yanıtlar:


113

Bu, bir borulu program (örn. Grep), önceki program tüm sayfayı yazmayı bitirmeden okuma borusunu kapattığında olur.

İçinde curl "url" | grep -qs foo, grep istediği şeye sahip olur olmaz, okuma akışını kıvrımdan kapatacaktır. cURL bunu beklemiyor ve "Başarısız yazı gövdesi" hatası veriyor.

Çözüm, akışı, bir sonraki programa beslemeden önce her zaman sayfanın tamamını okuyan bir aracı program aracılığıyla bağlamaktır.

Örneğin

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

tacgiriş sayfasının tamamını okuyan ve satır sırasını tersine çeviren basit bir Unix programıdır (dolayısıyla iki kez çalıştırırız). Son satırı bulmak için tüm girdiyi okuması gerektiğinden, cURL bitene kadar grep'e hiçbir şey göndermeyecektir. Grep, aradığı şeye sahip olduğunda okuma akışını yine de kapatacak, ancak yalnızca bir hata vermeyen tac'yi etkileyecektir.


5
Sadece bir catkez borulayamaz mıydınız? En azından benim için sorunu çözer.
benvd

5
Hayır. Küçük belgelerde yardımcı olabilir, ancak arabellek kedisine sığmayacak kadar büyük olduğunda hata yeniden görünür -s. İhtiyacınız yoksa tüm hata mesajlarını (ve ilerlemeyi) susturmak için kullanabilirsiniz .
Kaworu

9
tac|tacgiriş satır besleme ile bitmezse girişi değiştirir veya örneğin satır besleme olduğu yere printf a\\nb\\nc|tac|tacyazdırır . Bunun yerine kullanabilirsiniz . Başka bir seçenek , ancak giriş Zsh dışındaki kabuklarda boş bayt içerdiğinde, boş baytları atlar veya ilk boş bayttan sonra okumayı durdurur. a\ncb\nsponge /dev/stdoutprintf %s\\n "$(cat)"
nisetama

Dokümanlardan: CURLE_WRITE_ERROR (23) Alınan verileri yerel bir dosyaya yazarken bir hata oluştu veya libcurl'a bir yazma geri çağrısından hata döndürüldü. curl.haxx.se/libcurl/c/libcurl-errors.html
Jordan Stewart

3
Bu cevap kabul edilmelidir çünkü sorunu açıklar, ancak tacmacOS'ta herhangi bir komut olmadığı için yetenekli bir çözüm sunmaz
Dominik Bucher

49

Tamlık ve gelecekteki aramalar için:

CURL'nin arabelleği nasıl yönettiği meselesi, tampon -N seçeneğiyle çıkış akışını devre dışı bırakır.

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


8
Bunun için çalışma yaptı curl -s https://raw.githubusercontent.com/hermitdave/FrequencyWords/master/content/2016/ro/ro_50k.txt | head -20(olmadan -saynı hatayı alıyorum).
Dan Dascalescu

24

-o(Çıktı dosyası) seçeneği kullanılıyorsa başka bir olasılık - hedef dizin mevcut değildir.

Örneğin. varsa -o /tmp/download/abc.txtve / tmp / download mevcut değilse.

Bu nedenle, gerekli dizinlerin önceden oluşturulduğundan / var olduğundan emin olun, --create-dirsseçeneği kullanın - ogerekirse


2
Teşekkürler, --create-dirs bunu benim için en sıradışı durumda çözdü, neyin yanlış olduğunu anlayamadım, ama bilet buydu!
rfay

1
Sadece benzer bir durumda başıma geldi. Çıktı için değişken $ out bildirmeyi unuttum. Teşekkürler, Mike.
Mincong Huang

8

Kodlama sorunu vardı. Iconv sorunu çözdü

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

8

Bunu -oseçeneği kullanmak yerine yapabilirsiniz :

curl [url] > [file]


Peki, boru kullanarak değil, dosya sistemi üzerinde tüm işler yapmak? Kıvrımın çıkışını borularla kullanmak istedim.
statik

6

Aynı hatayı aldım ama farklı nedenlerden dolayı. Benim durumumda sadece 1GB alanla (tmpfs) bölümüm vardı ve sonunda bu bölümdeki tüm belleği dolduran büyük bir dosya indiriyordum ve sizinle aynı hatayı aldım.


5

Benim durumumda sunucuda disk alanı kalmadı.

İle kontrol edin df -k .

Https://stackoverflow.com/a/28879552/336694 adresindetac anlatıldığı gibi, iki kez geçmeyi denediğimde disk alanı olmadığı konusunda uyarıldım : https://stackoverflow.com/a/28879552/336694 . Bana hata mesajını gösterdi write error: No space left on device.


Aynı hatayı bir kapsayıcıdaki disk alanı tükenmesi nedeniyle aldım, çünkü aynı konuyu isabet eden herkes kapları içindeki alanı temizleyebilirdocker system prune
Dave

2

Ubuntu üzerinde vernik önbellek yüklemeye çalışırken bu hata iletisiyle karşılaştım. Google arama beni hataya (23) Failed writing bodygetirdi, böylece benim için çalışan bir çözüm gönderdi.

Komut root olarak çalıştırılırken hata ile karşılaşıldı curl -L https://packagecloud.io/varnishcache/varnish5/gpgkey | apt-key add -

çözüm apt-key addkök olmayan olarak çalıştırmaktır

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

1

Buna benzer bir şey deniyorsanız source <( curl -sS $url )ve (23) Failed writing bodyhatayı alıyorsanız, bunun nedeni bir işlem ikamesinin kaynaklanmasının işe bash 3.2yaramamasıdır (macOS için varsayılan).

Bunun yerine, bu geçici çözümü kullanabilirsiniz.

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

0

Benim için izin meselesiydi. Docker çalıştırması bir kullanıcı profiliyle çağrılır, ancak kök konteynerin içindeki kullanıcıdır. Çözüm / root için curl write yapmaktı, çünkü bu sadece root için değil, tüm kullanıcılar için yazma iznine sahipti.

-O seçeneğini kullandım.

-o / tmp / file_to_download


-1

Bash ve zsh'de (ve belki de diğer kabuklarda), anında bir dosya oluşturmak için işlem ikamesini ( Bash / zsh ) kullanabilir ve daha sonra bunu boru hattı zincirindeki bir sonraki işleme girdi olarak kullanabilirsiniz.

Örneğin, jqve kullanarak cURL JSON çıktı ayrıştırmaya çalışıyordu less, ama Failed writing bodyhata alıyordu .

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

Süreç ikamesi kullanarak yeniden yazdığımda işe yaradı!

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

Not: jqbir girdi dosyası belirtmek için 2. bağımsız değişkenini kullanır

Bonus: kullanıyorsanız jqbenim gibi ve istediğiniz colorized çıktı tutmak içinde less, yerine aşağıdaki komut satırını kullanın:

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

( Neden gerçekleştiğine dair açıklamalarından dolayı Kowaru'ya teşekkürler . Ancak, iki kez kullanma çözümleri benim için işe yaramadı. Ayrıca büyük dosyalar için daha iyi ölçeklenecek ve yorum olarak belirtilen diğer sorunlardan kaçınmaya çalışan bir çözüm bulmak istedim. bu cevaba.) Failed writing bodytac

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.