Life is Short

curl命令格式化输出请求各阶段的时间

curl 有一个参数 -w, --write-out <format> 可以在一次请求成功结束之后将跟该次请求相关的数据写到标准输出。
我们可以利用该功能将一次请求的各个阶段的时间格式化输出到屏幕以便查看分析问题。

首先, 我们查看man手册文档, 通过搜索定位到文档关于参数 -w, --write-out <format> 的描述位置,
可以看到关于这个文档的描述:

Defines what to display on stdout after a completed and successful operation. The format is a string that may contain plain text mixed with any number of vari‐
ables. The string can be specified as “string”, to get read from a particular file you specify it “@filename” and to tell curl to read the format from stdin you
write “@-“.

The variables present in the output format will be substituted by the value or text that curl thinks fit, as described below. All variables are specified as
%{variable_name} and to output a normal % you just write them as %%. You can output a newline by using \n, a carriage return with \r and a tab space with \t.

大致的意思如下:

定义在一次操作成功结束之后再标准输出中显示什么. 参数的格式可以是普通文本夹杂着预先定义好的变量.
参数可以通过命令行参数 “output format string” 来指定, 也可以通过 “@filename” 的格式来指定一个
文件, curl可以从该文件内读取 format 字符串, 或者也可以通过 “@-“ 的形式来告诉curl从标准输入内读取
format string .

curl会用合适的值或者文本来替换输出格式字符串中定义的变量. 所有的变量都以 %{variable_name} 的方式
来定义, 如果你想输出一个百分号(%), 写两个百分号(%%) 就好了. 你可以通过使用 \n 来输出一个换行, 也
可以使用 \r 来输出一个回车, 使用 \t 输出一个制表符.

在了解了该参数的含义后,我们从该参数后的变量列表里找出我们需要用到的预定义变量.
我需要用到的变量如下:(查看完整版的预定义变量列表请使用man curl 查看)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
time_appconnect
The time, in seconds, it took from the start until the SSL/SSH/etc connect/handshake to the remote host was completed. (Added in 7.19.0)(在https请求中, 跟对方主机建立安全连接所耗费的秒数)
time_connect The time, in seconds, it took from the start until the TCP connect to the remote host (or proxy) was completed.(跟对方主机建立tcp连接所耗费的秒数)
time_namelookup
The time, in seconds, it took from the start until the name resolving was completed.(DNS查询耗费的秒数)
time_pretransfer
The time, in seconds, it took from the start until the file transfer was just about to begin. This includes all pre-transfer commands and negotia‐
tions that are specific to the particular protocol(s) involved.(从操作开始到准备向对方发送请求内容所耗费的时间,包含了DNS查询或者协议处理的时间)
time_redirect The time, in seconds, it took for all redirection steps include name lookup, connect, pretransfer and transfer before the final transaction was
started. time_redirect shows the complete execution time for multiple redirections. (Added in 7.12.3)(该变量输出的是在最终请求发出前, 耗费在处理重定向的响应上的时间)
time_starttransfer
The time, in seconds, it took from the start until the first byte was just about to be transferred. This includes time_pretransfer and also the
time the server needed to calculate the result. (记录了从请求开始知道收到第一个字节耗费的秒数, 注意这个时间是包含了服务器处理请求的时间)
time_total The total time, in seconds, that the full operation lasted. The time will be displayed with millisecond resolution. (整个操作耗费的时间, 以毫秒计)

结合上面这些信息, 我们可以写出一个长长的format字符串来输出一个格式化的时间信息:

1
curl -o /dev/null -w "time_namelookup: %{time_namelookup}\ntime_appconnect: %{time_appconnect}\ntime_connect: %{time_connect}\ntime_redirect: %{time_redirect}\ntime_pretransfer: %{time_pretransfer}\ntime_starttransfer: %{time_starttransfer}\ntime_total: %{time_total}\n" -s TEST_URL

下图是我的一个测试:

curl-output-with-format-time

在 *UNIX 系统下, 我们可以将这个长长的命令保存为一个别名(alias), 方便以后的使用.
编辑 ~/.bashrc 文件, 添加如下一行:

1
alias curltime="curl -w \"time_namelookup: %{time_namelookup}\ntime_appconnect: %{time_appconnect}\ntime_connect: %{time_connect}\ntime_redirect: %{time_redirect}\ntime_pretransfer: %{time_pretransfer}\ntime_starttransfer: %{time_starttransfer}\ntime_total: %{time_total}\n\" -s"

好了,以后打开命令终端窗口, 需要的时候我们就可以以 curltime命令来代替curl命令从而获得额外的格式化过的时间统计数据的输出了.

注: 增加 -s 参数是为了让curl的输出变得更干净一点