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编码。可用命令 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

编码“application/x-www-form-urlencoded”也称为 Percent-encoding ,它使用 % 作为特殊字符的转义字符。比如特殊字符 & 当作普通字符时应该转义为 %26 (其中26为符号 & 的十六进制形式ASCII码值);又如换行符应该转义为 %0D%0A

参考:
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.1 实例:用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.2 实例:发送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:/images/json   # 列出docker images,仅在版本curl 7.40到curl 7.50(不含)可工作。不推荐用法

但curl 7.50中增加了对URL合法性的校验,需要写为下面的形式:

$ 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 00:00>

Last updated: <2018-07-19 Thu 13:36>

Creator: Emacs 25.3.1 (Org mode 9.1.4)