跳转至

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 的库版本写法。

评论