เหตุใดข้อผิดพลาดของ cURL ส่งคืนข้อผิดพลาด“ (23) เนื้อความการเขียนล้มเหลว”


153

มันทำงานได้ดีเป็นเครื่องมือเดียว:

curl "someURL"
curl -o - "someURL"

แต่มันไม่ทำงานในขั้นตอน:

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

มันกลับมา:

(23) Failed writing body

ปัญหาในการไพพ์เอาต์พุต cURL คืออะไร วิธีบัฟเฟอร์เอาต์พุต cURL ทั้งหมดจากนั้นจัดการ?


1
สำหรับฉันมันใช้งานได้ไม่จำเป็นต้องบัฟเฟอร์
hek2mgl

1
ทำงานในไปป์ไลน์ด้วยหรือไม่:curl 'http://www.multitran.ru/c/m.exe?CL=1&s=hello&l1=1' | tr -d '\n'
คงที่

1
เพิ่มแท็ก osx น่าเสียดายที่ฉันไม่สามารถช่วยได้ ฉันใช้ Linux
hek2mgl

1
ปัญหาคือการเข้ารหัสของหน้า (ไซริลลิ, win-1251) ดังนั้นฉันต้องใช้iconv -f ...
คงที่

5
เช่นเดียวกับคำใบ้อื่น: การขุดของฉันล้มเหลวเนื่องจากดิสก์เต็ม
Vince Varga

คำตอบ:


113

สิ่งนี้จะเกิดขึ้นเมื่อโปรแกรม piped (เช่น grep) ปิดไปป์อ่านก่อนที่โปรแกรมก่อนหน้าจะเขียนหน้าทั้งหมดเสร็จสิ้น

ในcurl "url" | grep -qs fooทันทีที่ grep มีสิ่งที่ต้องการมันจะปิดสตรีมการอ่านจาก curl cURL ไม่คาดหวังสิ่งนี้และส่งข้อผิดพลาด "เนื้อหาที่เขียนล้มเหลว"

วิธีแก้ไขคือไปป์ที่สตรีมผ่านโปรแกรมตัวกลางที่อ่านหน้าทั้งหมดก่อนที่จะป้อนเข้าสู่โปรแกรมถัดไป

เช่น

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

tacเป็นโปรแกรม Unix อย่างง่ายที่อ่านหน้าอินพุตทั้งหมดและกลับคำสั่งซื้อบรรทัด (ดังนั้นเราจึงรันสองครั้ง) เนื่องจากต้องอ่านอินพุตทั้งหมดเพื่อค้นหาบรรทัดสุดท้ายมันจะไม่เอาต์พุตอะไรให้ grep จนกว่า cURL จะเสร็จสิ้น Grep จะยังคงปิดสตรีมการอ่านเมื่อมีสิ่งที่ต้องการ แต่จะมีผลกับแทคซึ่งจะไม่ส่งข้อผิดพลาด


5
คุณไม่สามารถส่งผ่านcatเพียงครั้งเดียวได้หรือไม่ แก้ไขปัญหาให้ฉันอย่างน้อยที่สุด
benvd

5
ไม่มันอาจช่วยเอกสารขนาดเล็ก แต่เมื่อมันใหญ่เกินไปที่จะใส่ในบัฟเฟอร์ cat การใช้งานจะเกิดข้อผิดพลาดขึ้นอีกครั้งคุณสามารถใช้-sเพื่อปิดเสียงข้อความแสดงข้อผิดพลาดทั้งหมด (และความคืบหน้า) หากคุณไม่ต้องการ
Kaworu

9
tac|tacเปลี่ยนอินพุตหากอินพุตไม่ได้จบลงด้วย linefeed หรือตัวอย่างเช่นprintf a\\nb\\nc|tac|tacพิมพ์a\ncbที่\nlinefeed คุณสามารถใช้sponge /dev/stdoutแทน อีกตัวเลือกหนึ่งคือprintf %s\\n "$(cat)"แต่เมื่ออินพุตมี null null ในเชลล์ที่ไม่ใช่ Zsh นั่นจะข้ามไบต์ null หรือหยุดอ่านหลังจากไบต์แรกว่าง
nisetama

จากเอกสาร: CURLE_WRITE_ERROR (23) เกิดข้อผิดพลาดเมื่อเขียนข้อมูลที่ได้รับไปยังไฟล์โลคัลหรือข้อผิดพลาดถูกส่งกลับไปยัง libcurl จากการโทรกลับเพื่อเขียน curl.haxx.se/libcurl/c/libcurl-errors.html
Jordan Stewart

3
นี้ควรจะเป็นคำตอบที่ได้รับการยอมรับเพราะมันอธิบายปัญหา altought มันไม่ได้มีความสามารถในการแก้ปัญหาให้เป็นไม่มีtacคำสั่งบน MacOS
โดมินิก Bucher

49

สำหรับการค้นหาที่สมบูรณ์และในอนาคต:

มันเป็นเรื่องของวิธีที่ 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

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สองครั้งตามที่อธิบายไว้ในหนึ่งในคำตอบอื่น ๆ : https://stackoverflow.com/a/28879552/336694 write error: No space left on deviceมันแสดงให้ฉันเห็นข้อผิดพลาด


ผมได้รับข้อผิดพลาดเดียวกันเนื่องจากการทำงานออกจากพื้นที่ดิสก์ภายในภาชนะสำหรับคนอื่นยังตีปัญหาเดียวกันสามารถทำความสะอาดพื้นที่ภายในตู้คอนเทนเนอร์ของพวกเขาด้วยdocker system prune
เดฟ

2

ฉันพบข้อความแสดงข้อผิดพลาดขณะพยายามติดตั้งวานิชแคชบนอูบุนตู การค้นหา google ทำให้ฉันมีข้อผิดพลาดที่นี่ฉัน(23) Failed writing bodyจึงโพสต์โซลูชันที่เหมาะกับฉัน

พบข้อผิดพลาดขณะเรียกใช้คำสั่งในฐานะรูท 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

สำหรับฉันมันเป็นปัญหาสิทธิ์ นักวิ่งเรียกใช้ด้วยโปรไฟล์ผู้ใช้ แต่รูทเป็นผู้ใช้ภายในคอนเทนเนอร์ วิธีแก้ไขคือทำให้การเขียน curl ไปยัง / tmp เนื่องจากมีสิทธิ์การเขียนสำหรับผู้ใช้ทั้งหมดไม่ใช่แค่รูท

ฉันใช้ตัวเลือก -o

-o / tmp / file_to_download


-1

ใน Bash และ zsh (และบางทีเชลล์อื่น ๆ ) คุณสามารถใช้การทดแทนกระบวนการ ( Bash / zsh ) เพื่อสร้างไฟล์ได้ทันทีจากนั้นใช้สิ่งนั้นเป็นอินพุตไปยังกระบวนการถัดไปในไปป์ไลน์ไปป์ไลน์

ตัวอย่างเช่นฉันพยายามแยกเอาต์พุต JSON จาก cURL โดยใช้jqและ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

หมายเหตุ: jqใช้อาร์กิวเมนต์ตัวที่ 2 เพื่อระบุไฟล์อินพุต

โบนัส: หากคุณใช้งานjqเหมือนฉันและต้องการเก็บเอาท์พุท colorizedไว้lessให้ใช้บรรทัดคำสั่งต่อไปนี้แทน:

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

(ขอบคุณKowaruสำหรับคำอธิบายว่าทำไมถึง Failed writing bodyเกิดขึ้นอย่างไรก็ตามวิธีแก้ปัญหาในการใช้tacสองครั้งไม่ได้ผลสำหรับฉันฉันยังต้องการค้นหาวิธีแก้ปัญหาที่จะขยายขนาดให้ดีขึ้นสำหรับไฟล์ขนาดใหญ่และพยายามหลีกเลี่ยงปัญหาอื่น ๆ กับคำตอบนั้น)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.