蛮荆

curl 命令常用操作

2017-01-10

查看网页源码

$ curl https://dbwu.tech/

# 可以使用参数将网页内容保存到指定文件中
$ curl -o /tmp/index.html https://dbwu.tech/

跟踪跳转

# 请求会自动跟踪 
$ curl -L https://dbwu.tech/ 

显示响应头

$ curl -i https://dbwu.tech/ 

默认情况下,-i 选项会同时输出响应头部和内容,如果只希望输出响应头部,可以使用 -I 选项

$ curl -I https://dbwu.tech/

# 输出如下
HTTP/2 200 
content-type: text/html; charset=utf-8
access-control-allow-origin: *
cache-control: public, max-age=0, must-revalidate
referrer-policy: strict-origin-when-cross-origin
x-content-type-options: nosniff
vary: Accept-Encoding
cf-cache-status: DYNAMIC
server: cloudflare

...

隐藏响应内容

如果只希望确认通信双方是否可以正常通信,可以利用重定向到 /dev/null 文件来隐藏响应内容。

$ curl -o /dev/null https://dbwu.tech/ 

# 输出如下
# 例如可以用来检测文件的下载速度
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 19595    0 19595    0     0  14328      0 --:--:--  0:00:01 --:--:-- 14334

或者使用 -D - 参数,将响应头写到标准输出,同时配合 -o /dev/null 只输出响应头。

$ curl -D - -o /dev/null https://dbwu.tech

显示通信过程

$ curl -v https://dbwu.tech/ 

# 如果只希望输出响应头部,配合 -I 参数即可
$ curl -v -I https://dbwu.tech

# 输出如下
*   Trying [2606:4700:3036::ac43:936e]:443...
*   Trying 172.67.147.110:443...
* Connected to dbwu.tech (172.67.147.110) port 443
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256

...

* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://dbwu.tech/
* [HTTP/2] [1] [:method: HEAD]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: dbwu.tech]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.4.0]
* [HTTP/2] [1] [accept: */*]
> HEAD / HTTP/2
> Host: dbwu.tech
> User-Agent: curl/8.4.0
> Accept: */*
> 
< HTTP/2 200 
HTTP/2 200 

...

< 
* Connection #0 to host dbwu.tech left intact

显示通信过程详情

# 将输出内容保存到指定的文件中
$ curl --trace /tmp/trace.txt https://dbwu.tech

# 查看输出内容
$ cat /tmp/trace.txt

# 内容和使用抓包工具时的输出结果查不多
== Info:   Trying [2606:4700:3036::ac43:936e]:443...
== Info:   Trying 104.21.71.166:443...
== Info: Connected to dbwu.tech (2606:4700:3036::ac43:936e) port 443
== Info: ALPN: curl offers h2,http/1.1
== Info: (304) (OUT), TLS handshake, Client hello (1):
=> Send SSL data, 314 bytes (0x13a)
0000: 01 00 01 36 03 03 bf a9 1d ca c9 c6 43 9c 14 86 ...6........C...
0010: 2c d6 73 46 1e cd 89 f6 05 8f 27 e3 38 13 50 e9 ,.sF......'.8.P.
0020: be 0f 87 15 5b d1 20 c0 7d 3f 4e 03 0f b6 d8 b9 ....[. .}?N.....
0030: 7d b1 ca 9f c1 1b 12 85 1f f6 6f bc b4 09 ab fc }.........o.....

...
...

0910: 72 69 70 74 3e 3c 21 2d 2d 20 43 6c 6f 75 64 66 ript><!-- Cloudf
0920: 6c 61 72 65 20 50 61 67 65 73 20 41 6e 61 6c 79 lare Pages Analy
0930: 74 69 63 73 20 2d 2d 3e 3c 2f 62 6f 64 79 3e 0a tics --></body>.
0940: 0a 3c 2f 68 74 6d 6c 3e 0a 0a                   .</html>..
== Info: Connection #0 to host dbwu.tech left intact

发送表单数据

GET 请求

直接在 URL 后面拼接参数即可。

$ curl https://dbwu.tech/?page=2&pageSize=20

POST 请求

使用 –data 参数指定表单数据。

$ curl -X POST --data "username=dbwu" https://dbwu.tech

# 使用 --data-urlencode 进行自动编码
$ curl -X POST --data "request body" https://dbwu.tech

其他请求

直接使用 -X 参数配合对应的 HTTP 方法即可。

# 发送 PUT 请求
$ curl -X PUT  https://dbwu.tech

# 发送 DELETE 请求
$ curl -X DELETE  https://dbwu.tech

文件上传

$ curl -X POST -F "[email protected]" https://dbwu.tech 

指定 Referer

$ curl --referer https://google.com https://dbwu.tech 

指定 User Agent

$ curl --user-agent "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36" https://dbwu.tech  
$ curl --cookie "name=xxx" https://dbwu.tech

# 保存响应中的 cookie 到指定文件
$ curl -c /tmp/cookie.txt https://dbwu.tech

# 查看 cookie 文件
$ cat /tmp/cookie.txt 

# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.


# 使用指定文件作为 cookie 数据 (源) 文件
$ curl -b /tmp/cookie.txt https://dbwu.tech

设置请求头

$ curl --header "Content-Type:application/json" https://dbwu.tech

设置认证

$ curl --user username:password https://dbwu.tech

设置证书 (代理)

# 以特定证书访问某网站
$ curl -vvvv --cacert /path/to/root_ca.cer https://dbwu.tech

# 以特定代理访问某网站
$ curl -vvvv --proxy http://127.0.0.1:8080 https://dbwu.tech

访问 Socket

例如 Nginx 监听地址如下:

server {
        listen unix:/tmp/nginx.sock;
        
        ...
}
# --unix-socket 指定 unix socket 文件路径
$ curl --unix-socket /tmp/nginx.sock http://localhost/path

分析 HTTP 请求链路各阶段耗时

一个 HTTP 请求,会涉及到网络各层的工作时间,-w 参数允许用户自定义输出格式,可以显示请求和响应的各种信息。

下面是常用的 curl -w 参数选项:

  • %{url_effective}:请求 URL
  • %{http_code}:HTTP 响应状态码
  • %{http_connect}:从代理收到的 HTTP 响应代码
  • %{time_total}:完成请求的总时间,以秒为单位
  • %{time_namelookup}:DNS 解析花费时间,以秒为单位
  • %{time_connect}:TCP 连接建立所用时间,以秒为单位
  • %{time_appconnect}:SSL/SSH 握手所用时间,以秒为单位
  • %{time_pretransfer}:从客户端发起请求到准备传输数据所用时间,以秒为单位
  • %{time_starttransfer}:从客户端发起请求到开始接收响应的时间,以秒为单位
  • %{size_request}:请求的字节大小
  • %{size_upload}:上传的字节大小
  • %{size_download}:下载的字节大小
  • %{speed_download}:平均下载速度,以字节每秒为单位
  • %{speed_upload}:平均上传速度,以字节每秒为单位
  • %{content_type}:响应的 Content-Type

下面是一些使用 -w 参数的示例:

1. 显示 HTTP 状态码

$ curl -w "HTTP Status Code: %{http_code}\n" -o /dev/null -s https://www.dbwu.tech

# 输出如下

HTTP Status Code: 200

2. 显示请求总时间和 DNS 解析时间

$ curl -w "Total Time: %{time_total}\nDNS Lookup Time: %{time_namelookup}\n" -o /dev/null -s https://www.dbwu.tech

# 输出如下

Total Time: 0.382818
DNS Lookup Time: 0.006947

3. 显示多项信息

$ curl -w "HTTP Code: %{http_code}\nTotal Time: %{time_total}\nDownload Size: %{size_download}\n" -o /dev/null -s https://www.dbwu.tech

# 输出如下

HTTP Code: 200
Total Time: 0.478081
Download Size: 19493

4. 组合示例

下面是一个更复杂的示例,展示如何使用多个变量格式化输出:

$ curl -w "URL: %{url_effective}\nHTTP Code: %{http_code}\nTotal Time: %{time_total}\nDNS Lookup Time: %{time_namelookup}\nConnect Time: %{time_connect}\nPretransfer Time: %{time_pretransfer}\nStarttransfer Time: %{time_starttransfer}\nDownload Size: %{size_download}\nUpload Size: %{size_upload}\nDownload Speed: %{speed_download} bytes/sec\nUpload Speed: %{speed_upload} bytes/sec\nContent Type: %{content_type}\n" -o /dev/null -s https://www.dbwu.tech

# 输出如下

URL: https://www.dbwu.tech/
HTTP Code: 200
Total Time: 0.487167
DNS Lookup Time: 0.008145
Connect Time: 0.008359
Pretransfer Time: 0.333323
Starttransfer Time: 0.446315
Download Size: 19493
Upload Size: 0
Download Speed: 40012 bytes/sec
Upload Speed: 0 bytes/sec
Content Type: text/html; charset=utf-8

从输出结果中可以看到,请求中各个链路花费的时间:

  • DNS 查询时间: 0.008145 秒,也就是 8.1 毫秒
  • TCP 连接时间: 0.333323 - 0.008145 = 0.325178 秒,也就是 300 毫秒
  • 服务器处理时间:0.446315 - 0.333323 = 0.112992 秒,也就是 112 毫秒
  • 响应内容传输时间:0.487167 - 0.446315 = .040852 秒,也就是 40 毫秒

所以在整个请求中,占用时间最多的部分就是 TCP 三次握手建立连接的时间,占到了总时间的 60% 还多。

URL: %{url_effective}\n
HTTP Code: %{http_code}\n
Total Time: %{time_total}\n
DNS Lookup Time: %{time_namelookup}\n
Connect Time: %{time_connect}\n
Pretransfer Time: %{time_pretransfer}\n
Starttransfer Time: %{time_starttransfer}\n
Download Size: %{size_download}\n
Upload Size: %{size_upload}\n
Download Speed: %{speed_download} bytes/sec\n
Upload Speed: %{speed_upload} bytes/sec\n
Content Type: %{content_type}\n

5. 复用示例

如果希望复用 -w 的的输出格式,可以将格式写入文件中,然后 curl 访问时,通过 -w 参数来指定具体的文件名称即可。

例如将刚才的输出配置写入到 /tmp/curl-w.format 文件中。

$ cat /tmp/curl-w.format

# 输出如下
URL: %{url_effective}\n
HTTP Code: %{http_code}\n
Total Time: %{time_total}\n
DNS Lookup Time: %{time_namelookup}\n
Connect Time: %{time_connect}\n
Pretransfer Time: %{time_pretransfer}\n
Starttransfer Time: %{time_starttransfer}\n
Download Size: %{size_download}\n
Upload Size: %{size_upload}\n
Download Speed: %{speed_download} bytes/sec\n
Upload Speed: %{speed_upload} bytes/sec\n
Content Type: %{content_type}\n

使用 curl 访问时,通过将 -w 参数指定为具体的文件名称即可。

$ curl -w "@/tmp/curl-w.format" -o /dev/null -s  https://www.dbwu.tech

# 输出如下
URL: https://www.dbwu.tech/
HTTP Code: 200
Total Time: 0.394064
DNS Lookup Time: 0.008351
Connect Time: 0.008593
Pretransfer Time: 0.267342
Starttransfer Time: 0.352437
Download Size: 19493
Upload Size: 0
Download Speed: 49466 bytes/sec
Upload Speed: 0 bytes/sec
Content Type: text/html; charset=utf-8

Python 小工具

Github 上有一个类似功能的开源程序,链接: https://github.com/reorx/httpstat

dig 迭代查询示例

扩展阅读

转载申请

本作品采用 知识共享署名 4.0 国际许可协议 进行许可,转载时请注明原文链接,图片在使用时请保留全部内容,商业转载请联系作者获得授权。