curl

Table of Contents

1. curl 简介

curl 是基于 libcurl 开发的,功能强大的 URL 下载(上传)工具。

Since cURL uses libcurl, it supports a range of common Internet protocols, currently including HTTP, HTTPS, FTP, FTPS, SCP, SFTP, TFTP, LDAP, DAP, DICT, TELNET, FILE, IMAP, POP3, SMTP and RTSP (the last four only in versions newer than 7.20.0 or 9 February 2010).

参考:
curl man page: https://curl.haxx.se/docs/manpage.html
curl usage explained: https://curl.haxx.se/docs/manual.html
Using cURL to automate HTTP jobs: https://curl.haxx.se/docs/httpscripting.html
man curl
curl --help

2. curl 用法

curl 命令的基本格式为:

$ curl [options] [URL...]

2.1. 最基本实例

实例,下载网页(会直接显示到终端上):

$ curl http://www.gnu.org

实例,下载网页,保存为指定文件名。
方法 1:把标准输出重定向到某文件即可(这时终端会显示统计信息)。如:

$ curl http://www.gnu.org >1.html
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 27814    0 27814    0     0  22770      0 --:--:--  0:00:01 --:--:-- 23024

方法 2:使用“-o”选项(或“--output”选项)指定文件名。如:

$ curl http://www.gnu.org -o 2.html
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 27814    0 27814    0     0  20931      0 --:--:--  0:00:01 --:--:-- 21151

方法 3:使用“-O”选项(或“--remote-name”选项),这时保存的文件名就是 URL 中对应的名字(不能也无需指定保存的文件名)。如下载命令保存的文件名为 file1.html:

$ curl -O http://www.example.com/file1.html

2.2. URL 支持集合(大括号)或序列(中括号)

curl 中的 URL 参数支持用集合(用大括号表示)表示多个 URL,如:

http://site.{one,two,three}.com

curl 中的 URL 参数还支持用序列(用中括号表示)表示多个 URL,如:

ftp://ftp.example.com/file[1-100].txt
ftp://ftp.example.com/file[001-100].txt (with leading zeros)
ftp://ftp.example.com/file[a-z].txt

URL 中的序列还支持“步进”,如:

http://example.com/file[1-100:10].txt

相当于下面 10 个 URL:

http://example.com/file1.txt
http://example.com/file21.txt
http://example.com/file31.txt
http://example.com/file41.txt
http://example.com/file51.txt
http://example.com/file61.txt
http://example.com/file71.txt
http://example.com/file81.txt
http://example.com/file91.txt

2.3. 同时下载多个文件

curl 的“-o”和“-O”选项都可以一个命令行中同时指定多次。
如,用“-o”(或“--output”)同时下载 3 个文件:

$ curl http://www.example.com/test1.html -o test1.html http://www.example.com/test2.html -o test2.html http://www.example.com/test3.html -o test3.html
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
113   341  113   341    0     0    98k      0 --:--:-- --:--:-- --:--:--  166k
102  1124  102  1124    0     0  1455k      0 --:--:-- --:--:-- --:--:-- 1455k
100  5244  100  5244    0     0  6031k      0 --:--:-- --:--:-- --:--:-- 6031k

如,用“-O”(或“--remote-name”)同时下载 3 个文件:

$ curl -O http://www.example.com/test1.html -O http://www.example.com/test2.html -O http://www.example.com/test3.html
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
113   341  113   341    0     0    98k      0 --:--:-- --:--:-- --:--:--  166k
102  1124  102  1124    0     0  1455k      0 --:--:-- --:--:-- --:--:-- 1455k
100  5244  100  5244    0     0  6031k      0 --:--:-- --:--:-- --:--:-- 6031k

由于上面的多个 URL 之间有一定的规则,还可以简化为下面命令:

$ curl -O "http://www.example.com/test[1-3].html"
$ curl "http://www.example.com/test[1-3].html" -o "test#1.html"

说明:上面命令中“-o”参数“test#1.html”中的“#1”会替换为“[1-3]”被处理时的内容。详情请看下文。

2.3.1. 用#number 引用 URL 中的集合或序列

用“#number”可以引用 URL 中的集合或序列。
如,命令:

$ curl "http://{one,two}.site[1-3].com" -o "file_#1_#2.html"

相当于:

$ curl http://one.site1.com -o file_one_1.html
$ curl http://one.site2.com -o file_one_2.html
$ curl http://one.site3.com -o file_one_3.html
$ curl http://two.site1.com -o file_two_1.html
$ curl http://two.site2.com -o file_two_2.html
$ curl http://two.site3.com -o file_two_3.html

2.4. 打开 verbose 模式(-v)

要打开 curl 的 verbose 模式,可以指定“-v”选项(或“-verbose”选项)。

2.5. 跟进 HTTP 响应报文头中的 Location 字段(-L)

访问某些网站时,可能服务器会返回 302 状态(Temporarily Moved),并在响应报文头中设置 Location 字段。

使用“-L”选项(或“--location”选项)可以使 curl 跟进 Location 字段,继续下载操作。如:

$ curl http://www.google.com
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.co.jp/?gfe_rd=cr&amp;ei=BcihV9GYLNHU8Afmh4KICQ">here</A>.
</BODY></HTML>

访问 http://www.google.com 时返回的是 302,使用“-L”可以使 curl 跟进 Location 字段,继续下载操作。如:

$ curl -L http://www.google.com >1.html

2.6. 增加字段到 HTTP 请求报文头(-H)

用“-H”选项(或“--head”选项)可以增加字段到 HTTP 请求报文头。“-H”选项可以同时指定多次。

如:

$ curl -H "X-First-Name: Joe" -H "X-Last-Name: Bill" http://192.168.0.1/
$ curl -H "Authorization: Basic dXNlcjE6cGFzc3dkMQ==" http://192.168.0.1/

说明:上例中“dXNlcjE6cGFzc3dkMQ==”是“user1:passwd1”的 Base64 编码(这种认证方式在 RFC 7617 中定义)。可用命令 base64 验证,如:

$ echo dXNlcjE6cGFzc3dkMQ== |base64 --decode
user1:passwd1

2.6.1. 实例:禁止 Cache

下面例子可以禁止 Cache:

$ curl -H 'Cache-Control: no-cache' http://192.168.0.1/

2.7. HTTP 认证(-u 或-H)

可以用“-u”选项(或“--user”选项)指定 HTTP 认证。

下面两个命令的作用相同。

$ curl -u user1:passwd1 http://example.com
$ curl -H "Authorization: Basic dXNlcjE6cGFzc3dkMQ==" http://example.com

注:curl 对于 http 协议默认使用“Basic HTTP Authentication”,例子中“dXNlcjE6cGFzc3dkMQ==”是“user1:passwd1”的 Base64 编码。

2.8. 定制报文头中的请求方法(-X)

默认地,http 请求的方法是 GET,可以使用“-X”修改请求方法为“PUT”、“DELETE”等等。如,发送 DELETE 命令到某个 URL:

$ curl -X DELETE http://www.example.com/page1

2.9. 输出响应报文头(-i)

用“-i”选项(或“--include”选项),会同时输出响应报文头。如:

$ curl -i http://www.google.com
HTTP/1.1 302 Found
Date: Thu, 02 Aug 2012 02:21:14 GMT
Location: http://www.google.co.jp/?gfe_rd=cr&ei=mqaiV-ykHs_U8Af3qoHAAw
Content-Type: text/html; charset=UTF-8
Cache-Control: private
Content-Length: 261
Proxy-Connection: Keep-Alive

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.co.jp/?gfe_rd=cr&amp;ei=mqaiV-ykHs_U8Af3qoHAAw">here</A>.
</BODY></HTML>

说明:如果要显示请求报文头,可以使用 verbose 模式(“-v”选项)。

2.10. 只获取响应报文头(-I)

用“-I”选项(或“--head”选项),可以只获取响应的报文头。

2.11. 定制输出格式(-w)

用“-w”选项(或“--write-out”选项),可以定制输出格式。

2.11.1. 实例:获取 Http Status Code

使用 -w '%{http_code}' 可以方便地得到 Http Status Code,不用 parse 输出了。如:

STATUS=$(curl -s -o /dev/null -w '%{http_code}' http://example.com)
if [ $STATUS -eq 200 ]; then
  echo "Got 200! All done!"
else
  echo "Got $STATUS."
fi

2.12. 发送 HTTP POST 请求(-d,--data 或-F,--form)

curl 中使用“-d(--data)”和“-F(--form)”都会默认发送 POST 请求。

Table 1: curl 中-d(--data)和-F(--form)选项
选项 默认 method 默认 Content-Type
-d/--data <data> POST Content-Type: application/x-www-form-urlencoded
-F/--form <name=content> POST Content-Type: multipart/form-data

说明:application/x-www-form-urlencoded 和 multipart/form-data 是两种不同格式的 form 数据。一般地,发送纯 ASCII 文本可以使用 application/x-www-form-urlencoded,而发送二进制数据或非 ASCII 数据则要使用 multipart/form-data。

实例:

$ curl --data "param1=value1&param2=value2" http://localhost:8000/resource.cgi

2.12.1. application/x-www-form-urlencoded 标准

application/x-www-form-urlencoded 是 RFC1738 的变种(或者说是 RFC3986 的变种):对 ASCII 使用下面的规则:
1、下面 3 类字符不转义,原样输出:

  • 英文字母(大写和小写)
  • 0-9 共 10 个数字
  • -_. (连字符,下划线,点号共 3 个字符)

2、英文空格变为加号 +
3、所有其它字符变为 % 加其两位十六进制数(大写形式),比如 * 转为 %2A

参考:
Form content types: https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4
http://stackoverflow.com/questions/4007969/application-x-www-form-urlencoded-or-multipart-form-data

2.12.2. 实例:用 POST 方法发送 json 数据

实例,用 POST 方法发送 json 数据到指定 URL:

$ curl -X POST -H "Content-Type: application/json" -d '{"username":"xyz","password":"xyz"}' http://localhost:8000/api/login

如果 json 数据在文件中(如文件名为 body.json),则可以通过“-d @body.json”来引用它(注意文件名前面有符号@)。如:

$ curl -X POST -H "Content-Type: application/json" -d @body.json http://localhost:8000/api/login

说明:前面例子中“-X POST”可以省略,使用“-d(--data)”时默认为 POST 方法。

2.12.3. 实例:发送 multipart/form-data 类型的请求

使用 curl 的“-F”选项可以发送 multipart/form-data 类型的请求。如:

$ curl -v -F key1=value1 -F key2=value2 http://localhost:8000/yourendpoint

上面命令发送的 HTTP 报文类似于:

POST /yourendpoint HTTP/1.1
Host: localhost:8000
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="key1"

value1
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="key2"

value2
------WebKitFormBoundary7MA4YWxkTrZu0gW--

也可以发送二进制数据,这时需要指定文件路径(路径前面加@符号),如:“-F xxx=@/path/to/image.jpg”。

参考:
https://www.ietf.org/rfc/rfc1867.txt
http://stackoverflow.com/questions/19116016/what-is-the-right-way-to-post-multipart-form-data-using-curl

2.13. 发送 Unix socket

在 curl 7.40 中增加了对 Unix socket 的支持,你可以使用 curl --version 检查 curl 的版本。

下面是使用 curl 获取 docker images 的例子:

$ curl --unix-socket /var/run/docker.sock http://localhost/images/json  # 列出docker images,在版本curl 7.40及更高版本都可工作

2.14. 断点续传(-C)

用“-C”选项(或“--continue-at”选项)可以实现断点续传。

使用“-C”时,后面要接 offset,如果要 curl 自动判断,则 offset 可写为“-”,即使用“-C -”时 curl 会自动判断从哪个位置继续下载。

$ curl -O http://ftp.gnu.org/pub/gnu/emacs/emacs-23.4.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  6 45.5M    6 3179k    0     0   511k      0  0:01:31  0:00:06  0:01:25  614k
<Ctrl+C>

$ curl -C - -O http://ftp.gnu.org/pub/gnu/emacs/emacs-23.4.tar.gz
 Resuming transfer from byte position 3801088
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (33) HTTP server doesn't seem to support byte ranges. Cannot resume.

说明:断点续传需要服务器的支持(上面例子中的服务器不支持断点续传)。

2.15. ftp 服务器下载和上传

从 ftp 服务器下载文件,直接指定 ftp 服务器中的想要下载的文件的 URL 即可。如:

$ curl -O ftp://ftp.example.com/1.txt

2.15.1. 指定用户名和密码(-u)

上传或下载时,如果要指定用户名和密码,可以使用“-u”选项(或“--user”选项)来指定。如:

$ curl -u user1:passwd1 -O ftp://ftp.example.com/1.txt

2.15.2. 下载目录时其行为是“列出”目录内容

如果指定 ftp 的 URL 为目录,而不是文件,则会“列出”目录内容。如:

$ curl -O ftp://ftp_server/public_html/      # 会列出目录内容,不会下载整个目录。

注:curl 时无法直接下载整个 ftp 目录。

2.15.3. 上传文件到 ftp/http 服务器(-T)

用“-T”选项(或“--upload-file”选项)可以上传文件到 ftp 服务器。如:

$ curl -u user1:passwd1 -T file1.txt ftp://ftp.example.com/
2.15.3.1. 使用“-T”时如果 URL 为 http 协议,则使用 HTTP 的 PUT 方法

使用“-T”时如果 URL 为 http 协议,则使用 HTTP 的 PUT 方法。如:

$ curl -T file1.txt http://www.example.com/dir/
2.15.3.2. 同时上传多个文件到 ftp 服务器

我们知道,curl 中可以用集合(大括号)或序列(中括号)表示 URL。除此外,还可以用集合(大括号)或序列(中括号)来表示想要上传的多个文件。如:

$ curl -T "{file1,file2}" ftp://ftp.example.com/
$ curl -T "img[1-1000].png" ftp://ftp.example.com/

2.16. 指定 ca certificate(--cacert)

curl 访问 https 服务器(或其它开户了 tls 的服务器,如 ftps 等),但 https 服务器的证书不是知名 CA 签发的(比如自己搭建的 CA 签发的),这时,用户可通过参数 --cacert path/to/cacert.pem 来指定 CA 证书的位置以便 curl 验证 https 服务器。

注 1:使用 -k 或者 --insecure 选项可以跳过对 https 服务器的验证。
注 2:curl 内置了知名 CA 的证书,其位置可以通过 strace curl https://www.google.com 2>&1 | grep open 命令显示出来,参考https://serverfault.com/questions/485597/default-ca-cert-bundle-location

Author: cig01

Created: <2011-04-24 Sun>

Last updated: <2019-05-07 Tue>

Creator: Emacs 27.1 (Org mode 9.4)