为啥 cURL 返回错误“(23) Failed writing body”?

Posted

技术标签:

【中文标题】为啥 cURL 返回错误“(23) Failed writing body”?【英文标题】:Why does cURL return error "(23) Failed writing body"?为什么 cURL 返回错误“(23) Failed writing body”? 【发布时间】:2013-05-18 04:56:48 【问题描述】:

它可以作为一个单独的工具工作:

curl "someURL"
curl -o - "someURL"

但它在管道中不起作用:

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

它返回:

(23) Failed writing body

管道 cURL 输出有什么问题?如何缓冲整个 cURL 输出然后进行处理?

【问题讨论】:

对我来说它可以工作,不需要缓冲。 这在管道中也可以工作吗?:curl 'http://www.multitran.ru/c/m.exe?CL=1&s=hello&l1=1' | tr -d '\n' 添加了 osx 标签。不幸的是,我对此无能为力。我正在使用 Linux 问题是页面编码(西里尔文,win-1251)。所以我必须使用iconv -f ... 正如另一个提示:我的失败,因为磁盘已满。 【参考方案1】:

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

curl "url" | grep -qs foo 中,一旦 grep 得到它想要的内容,它将关闭 curl 的读取流。 cURL 没有预料到这一点,并发出“Failed writing body”错误。

一种解决方法是通过一个中间程序对流进行管道传输,该中间程序总是在将整个页面提供给下一个程序之前读取整个页面。

例如

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

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

【讨论】:

你能不能简单地通过cat 传递一次?至少为我解决了这个问题。 没有。它可能对小文档有所帮助,但是当它太大而无法放入缓冲区时,错误会再次出现。如果您不需要它们,可以使用 -s 将所有错误消息(和进度)静音。 tac|tac 如果输入不以换行结束,则更改输入,或者例如printf a\\nb\\nc|tac|tac 打印a\ncb 其中\n 是换行。您可以改用sponge /dev/stdout。另一个选项是printf %s\\n "$(cat)",但是当输入在 Zsh 以外的 shell 中包含空字节时,它要么跳过空字节,要么在第一个空字节之后停止读取。 这应该被接受,因为它解释了问题,但它没有提供有效的解决方案,因为 macOS 上没有 tac 命令 我只是忽略了stderr并将其发送到null:curl "url" 2>/dev/null | grep【参考方案2】:

为了完整性和未来的搜索:

这是cURL如何管理缓冲区的问题,缓冲区使用-N选项禁用输出流。

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

【讨论】:

它确实适用于curl -s https://raw.githubusercontent.com/hermitdave/FrequencyWords/master/content/2016/ro/ro_50k.txt | head -20(没有-s 我得到同样的错误)。 -s 只是让 curl 静默,所以它不会发出你会看到的错误。潜在的问题仍在发生,但在大多数情况下这都很好。但是,如果您正在执行类似 curl ... | tee /tmp/full_output | head -20 的操作,那么如果您希望 /tmp/full_output 拥有一切,则需要实际解决错误。【参考方案3】:

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

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

因此,请确保事先创建/存在任何所需的目录,如有必要,请使用 --create-dirs 选项以及 -o

【讨论】:

谢谢,--create-dirs 在最不寻常的情况下为我解决了这个问题,无法弄清楚出了什么问题,但这就是票! 我也遇到过类似的情况。我忘了为输出声明变量 $out。谢谢,迈克。【参考方案4】:

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

df -k .检查它

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

【讨论】:

由于容器内的磁盘空间不足,我收到了同样的错误,因为其他遇到同样问题的人可以使用docker system prune清理其容器内的空间【参考方案5】:

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

curl [url] > [file]

【讨论】:

那么,不使用管道而是在文件系统上完成所有工作?我想将 curl 的输出与管道一起使用。【参考方案6】:

所以这是编码的问题。 Iconv 解决问题

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

【讨论】:

【参考方案7】:

我有同样的错误,但原因不同。在我的情况下,我的 (tmpfs) 分区只有 1GB 空间,我正在下载大文件,最终 填满了该分区上的所有内存,我遇到了和你一样的错误。

【讨论】:

【参考方案8】:

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

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

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

【讨论】:

【参考方案9】:

对我来说,这是权限问题。 Docker run 使用用户配置文件调用,但 root 是容器内的用户。解决方案是让 curl 写入 /tmp,因为它对所有用户都有写权限,而不仅仅是 root。

我使用了 -o 选项。

-o /tmp/file_to_download

【讨论】:

是的,当您通常以非特权用户身份运行创建 tmp 文件的脚本,然后以 root 身份运行该脚本一次以测试某事时,这可能会让您感到意外。稍后,非特权用户将无法使用/清理 root 留下的临时文件。在创建 tmp 文件后,我总是尝试将“chown user:”放入我的脚本中。【参考方案10】:

就我而言,我正在做: curl &lt;blabla&gt; | jq | grep &lt;blibli&gt;

jq . 一起工作:curl &lt;blabla&gt; | jq . | grep &lt;blibli&gt;

【讨论】:

【参考方案11】:

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

sudo curl -O -k 'https url here'

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

【讨论】:

【参考方案12】:

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

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 -

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

【讨论】:

【参考方案13】:

我在 ubuntu 上尝试安装清漆缓存时遇到此错误消息。谷歌搜索将我带到这里是因为错误 (23) Failed writing body,因此发布了一个对我有用的解决方案。

以root身份运行命令时遇到错误curl -L https://packagecloud.io/varnishcache/varnish5/gpgkey | apt-key add -

解决方案是以非 root 身份运行 apt-key add

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

【讨论】:

【参考方案14】:

在 Bash 和 zsh(可能还有其他 shell)中,您可以使用进程替换 (Bash/zsh) 即时创建文件,然后将其用作管道链中下一个进程的输入.

例如,我尝试使用 jqless 解析来自 cURL 的 JSON 输出,但遇到了 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 使用它的第二个参数来指定输入文件

奖励:如果您像我一样使用jq 并想在less 中使用keep the colorized output,请改用以下命令行:

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

(感谢Kowaru 对为什么 Failed writing body 发生的解释。但是,他们使用tac 两次的解决方案对我不起作用。我还想找到一个解决方案可以更好地扩展大文件,并尝试避免该答案中提到的其他问题。)

【讨论】:

不知道为什么投反对票......这个答案似乎对我有补充和帮助

以上是关于为啥 cURL 返回错误“(23) Failed writing body”?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 curl_exec($url) 返回空字符串

php获取数据为啥curl获取不完整

Jenkinsfile/Groovy:为啥 curl 命令会导致“错误请求”

为啥在此 cURL 调用中的请求正文中出现格式错误的 JSON?

为啥我收到致命错误:未捕获的异常 'GuzzleHttp\Exception\RequestException' 和消息 'cURL 错误 60

为啥我的 cURL 请求在 XAMPP 中不起作用?