curl 详解
curl 是最通用的命令行 HTTP 客户端:调试接口、下载文件、在脚本里探活都靠它。所有示例可对照本地服务执行,基础用法见常用命令速查网络一节,图形化替代品不重要——curl 才是文档里示例语言的通用语。
调试一次请求:-i 与 -v
curl -i https://httpbin.org/get # 输出响应头 + 响应体
curl -I https://httpbin.org/get # 只看响应头(发 HEAD 请求)
curl -v https://httpbin.org/get # 全过程:DNS、TCP/TLS 握手、请求头、响应头逐条打印
-v 的输出分三栏:> 发出的请求、< 收到的响应、* 连接层信息——看懂 -v 就能解释九成的"请求为什么不对"(头没带上、被重定向、代理介入一目了然)。要更细的原始字节用 --trace-ascii dump.txt。
发送数据:方法、体与头
# POST JSON(最常见的接口调用)
curl -X POST https://httpbin.org/post \
-H "Content-Type: application/json" \
-d '{"name": "ada", "score": 90}'
# 表单提交(application/x-www-form-urlencoded)
curl -d "user=ada&pass=secret" https://httpbin.org/post
# 自定义头(可重复 -H)
curl -H "X-Token: abc123" -H "Accept: application/json" https://httpbin.org/get
# Bearer 认证(JWT 场景)
curl -H "Authorization: Bearer eyJhbGci..." https://api.example.com/me
# Basic 认证
curl -u user:password https://httpbin.org/basic-auth/user/password
# 文件上传(multipart/form-data)
curl -F "[email protected]" -F "note=monthly" https://httpbin.org/post
注意 -d 出现时默认方法就是 POST,-X POST 可以省略;-X 只在方法与 -d/-F 推断不一致时才需要写(例如 -X DELETE)。
重定向与状态码
curl -L https://example.com # 跟随 3xx 重定向(默认不跟)
curl -L --max-redirs 5 URL # 限制跳转次数
curl -o /dev/null -s -w "%{http_code} %{redirect_url}\n" URL # 只看状态码与跳转目标
-w(write-out)按格式串输出统计,是脚本探活的标准工具:
curl -o /dev/null -s -w "code=%{http_code} total=%{time_total}s connect=%{time_connect}s\n" \
https://example.com
# 常用变量:%{http_code} %{time_namelookup} %{time_connect} %{time_appconnect}(TLS)
# %{time_starttransfer}(TTFB) %{time_total} %{size_download}
时延分解的用法与解读见性能排查工具箱。
下载
curl -O https://example.com/file.tar.gz # 用服务器上的文件名保存
curl -o out.tar.gz URL # 自定义保存名
curl -C - -O URL # 断点续传(接着上次未完成的下)
curl --limit-rate 1M -O URL # 限速下载
curl -sS -o page.html URL # -s 静默进度 + -S 出错时仍显示错误
超时与重试
curl --connect-timeout 3 --max-time 30 URL # 连接 3 秒 / 整体 30 秒
curl --retry 3 --retry-delay 2 URL # 失败重试(含瞬态错误)
curl --retry 3 --retry-connrefused URL # 连接被拒也重试(等服务启动的探活写法)
在脚本里用 curl
# 健康检查:显式失败 + 明确退出码(退出码表见文末)
if curl -fsS --max-time 5 -o /dev/null http://127.0.0.1:8080/health; then
echo "service up"
else
echo "service down" >&2
exit 1
fi
# 调 JSON 接口并格式化(没有 jq 时用 python)
curl -s https://httpbin.org/json | python -m json.tool
-f(--fail)让 HTTP 错误状态码直接反映为非零退出码——脚本里探活必加,否则 404/500 也算"成功"。-sS 组合(静默进度但保留错误信息)同样是脚本标配。
常见错误
| 错误 | 说明 |
|---|---|
URL 里的 & 没加引号 |
curl URL?a=1&b=2 中 & 是 shell 的后台符号,命令被截断——URL 一律加引号 |
忘记 -H "Content-Type: application/json" |
服务端收到 JSON 体却按表单解析 |
-k(关闭证书校验)随手用 |
掩盖证书问题且中间人风险;自签名场景改用 --cacert 指定 CA |
探活脚本不加 -f |
服务返回 500 时 curl 退出码仍是 0,监控误报"正常" |
POST 405 |
写了 -d 却又想用 GET:-d 默认 POST;显式声明用 -X GET + --data 组合或 -G 把数据放查询串 |
| 413 上传被拒 | 代理侧体积限制(Nginx 默认 1MB,见Nginx 入门) |
| 偶发 SSL 错误 | 本机系统时间不对会导致证书校验失败(有效期判断错乱) |
退出码速查(脚本判断用)
| 退出码 | 含义 |
|---|---|
| 0 | 成功(-f 时指 HTTP 状态也不算失败) |
| 6 | 无法解析主机(DNS) |
| 7 | 连接被拒/无法连接 |
| 28 | 超时(--max-time 到点) |
| 22 | HTTP 状态 ≥ 400(需配合 -f) |
| 60 | 证书校验失败 |
相关:性能排查工具箱的网络分层排查、SSH 隧道把内网接口映射到本地后再 curl、Python requests 的库版本写法。