209

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

curl "someURL"
curl -o - "someURL"

但它在管道中不起作用:

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

它返回:

(23) Failed writing body

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

4

14 回答 14

150

当管道程序(例如 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,它不会发出错误。

于 2015-03-05T13:58:14.197 回答
72

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

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

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

于 2016-02-23T13:36:25.720 回答
45

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

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

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

于 2018-01-24T10:46:16.663 回答
13

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

检查它df -k .

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

于 2018-02-20T15:59:56.473 回答
11

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

curl [url] > [file]

于 2013-07-14T19:07:03.473 回答
11

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

curl 'http://www.multitran.ru/c/m.exe?CL=1&s=hello&l1=1' | iconv -f windows-1251 | tr -dc '[:print:]' | ...
于 2013-05-23T11:00:08.267 回答
6

I had the same error but from different reason. In my case I had (tmpfs) partition with only 1GB space and I was downloading big file which finally filled all memory on that partition and I got the same error as you.

于 2017-03-30T16:04:52.910 回答
5

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

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

source /dev/stdin <<<"$( curl -sS $url )"
于 2019-08-31T00:05:58.570 回答
4

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

我使用了 -o 选项。

-o /tmp/file_to_download

于 2019-03-20T10:57:07.647 回答
4

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

sudo curl -O -k 'https url here'

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

于 2021-09-26T02:32:49.460 回答
4

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

有了jq .它:curl <blabla> | jq . | grep <blibli>

于 2020-11-23T05:13:01.140 回答
3

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

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错误。

于 2021-01-07T05:47:16.317 回答
2

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

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

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

curl -L https://packagecloud.io/varnishcache/varnish5/gpgkey | apt-key add -
于 2018-02-01T09:35:54.287 回答
0

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

例如,我试图使用jqand解析来自 cURL 的 JSON 输出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使用它的第二个参数来指定一个输入文件

奖励:如果您jq像我一样使用并希望将彩色输出保留在less,请改用以下命令行:

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

(感谢Kowaru对发生原因 的解释Failed writing body。但是,他们使用tac两次的解决方案对我不起作用。我还想找到一个可以更好地适应大文件的解决方案,并尽量避免注释中提到的其他问题到那个答案。)

于 2020-05-14T18:15:50.080 回答