为什么CURL返回和错误(23)写入正文失败?

sta*_*tic 115 macos bash curl pipe osx-lion

它作为一个工具正常工作:

curl "someURL"
curl -o - "someURL"
Run Code Online (Sandbox Code Playgroud)

但它不适用于管道:

curl "someURL" | tr -d '\n'
curl -o - "someURL" | tr -d '\n'
Run Code Online (Sandbox Code Playgroud)

它返回:

(23) Failed writing body
Run Code Online (Sandbox Code Playgroud)

卷曲输出管道有什么问题?如何缓冲整个curl输出然后处理它?

Kaw*_*oru 97

当一个管道程序(例如grep)在前一个程序写完整个页面之前关闭读取管道时会发生这种情况.

curl "url" | grep -qs foo,只要grep有它想要的东西,它就会关闭curl的读取流.cURL不期望这样并且发出"失败的写入正文"错误.

解决方法是通过中间程序管道流,该程序始终在将其提供给下一个程序之前读取整个页面.

例如

curl "url" | tac | tac | grep -qs foo
Run Code Online (Sandbox Code Playgroud)

tac是一个简单的Unix程序,它读取整个输入页面并反转行顺序(因此我们运行它两次).因为它必须读取整个输入才能找到最后一行,所以在cURL完成之前它不会向grep输出任何内容.当Grep具有它正在寻找的内容时,它仍会关闭读取流,但它只会影响tac,它不会发出错误.

  • 如果输入没有以换行结束,`tac | tac`会改变输入,或者例如`printf a \\nb \\nc | tac | tac`打印`a \ncb`,其中`\n`是换行符.您可以使用`sponge/dev/stdout`代替.另一个选项是`printf%s \\n"$(cat)"`,但是当输入在Zsh以外的shell中包含空字节时,它会跳过空字节或在第一个空字节后停止读取. (7认同)
  • 难道你不能简单地通过`cat`管道一次吗?至少为我解决了这个问题. (4认同)
  • 不.它可能对小文档有帮助,但是当它太大而无法放入缓冲区时,cat会重新出现.如果你不需要,你可以使用`-s`来静音所有错误信息(和进度). (4认同)
  • 这应该被接受,因为它解释了问题,虽然它没有提供有效的解决方案,因为 macOS 上没有 `tac` 命令 (3认同)

小智 29

(为了完整性和将来的搜索)这是CURL如何管理缓冲区的问题,缓冲区使用-N选项禁用输出流.

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

  • 它适用于`curl -s https://raw.githubusercontent.com/hermitdave/FrequencyWords/master/content/2016/ro/ro_50k.txt | 头-20`(没有`-s`我得到同样的错误). (5认同)

Mik*_*keW 16

另一种可能性,如果使用-o(输出文件)选项 - 目标目录不存在.

例如.如果你有-o /tmp/download/abc.txt和/ tmp/download不存在.

因此,请确保事先创建/存在任何所需目录,并在必要时使用该--create-dirs选项o

  • 谢谢,--create-dirs 在最不寻常的情况下为我解决了这个问题,无法找出问题所在,但这就是票! (3认同)

wis*_*cky 11

如果您尝试类似的操作source <( curl -sS $url )并收到错误,那是因为采购进程替换在(macOS 的默认设置)(23) Failed writing body中不起作用。bash 3.2

相反,您可以使用此解决方法。

source /dev/stdin <<<"$( curl -sS $url )"
Run Code Online (Sandbox Code Playgroud)


sta*_*tic 9

所以这是一个编码问题.Iconv解决了这个问题

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


use*_*192 8

尝试该命令sudo对我有用。例如:

sudo curl -O -k 'https url here'
Run Code Online (Sandbox Code Playgroud)

注意:-O(这是大写的 o,不是零)& -k 表示 https url。


小智 7

您可以这样做而不是使用-o选项:

curl [url] > [file]

  • 问题是只有管道序列不起作用. (2认同)

LLL*_*LLL 7

我有同样的错误,但出于不同的原因.在我的情况下,我有(tmpfs)分区只有1GB的空间,我正在下载大文件,最终填充该分区上的所有内存,我得到了与你相同的错误.


小智 6

我在做的时候遇到了同样的问题:

curl -L https://packagecloud.io/golang-migrate/migrate/gpgkey | apt-key add -

上述查询需要使用root权限执行。

按照以下方式编写它解决了我的问题:

curl -L https://packagecloud.io/golang-migrate/migrate/gpgkey | sudo apt-key add -

如果你sudo之前写的话curl,你会得到Failed writing body错误。


Hos*_*com 5

就我而言,服务器的磁盘空间不足。

用它检查 df -k .

tac如其他答案之一所述,当我尝试通过两次管道传输时,我收到磁盘空间不足的警告:https : //stackoverflow.com/a/28879552/336694。它向我显示了错误消息write error: No space left on device


dam*_*mio 5

就我而言,我正在做: curl <blabla> | jq | grep <blibli>

jq .它工作:curl <blabla> | jq . | grep <blibli>