curl 命令实战

curl 是命令行下最强大的 HTTP 客户端,前后端开发者每天都离不开它。这一章按真实开发场景组织——GET、POST、上传、认证、Cookie、HTTPS、代理、性能——配可复制的命令。

1. curl 是什么

curl(client URL)是一个开源的命令行工具,支持 HTTP/HTTPS/FTP/SMTP 等十几种协议。Linux/macOS 系统自带(Windows 10+ 也内置了),所以是脚本里做 HTTP 调试最通用的选择。它的双胞胎是 libcurl,几乎所有编程语言都有基于它的库。

2. 基础用法

# 最简单的 GET
curl https://example.com/

# 加 -v 看请求和响应的完整报文 (调试神器)
curl -v https://example.com/

# 加 -i 只看响应头 (包含状态行)
curl -i https://example.com/

# 加 -o 保存到文件,-L 跟随重定向
curl -L -o page.html https://example.com/

# 加 -s 静默 (不显示进度条),-S 配合显示错误
curl -sS https://example.com/ -o /dev/null -w '%{http_code}\n'

3. GET 请求与自定义头

# GET 带查询参数: 直接拼在 URL 里 (URL 加引号防 & 被 shell 解释)
curl 'https://api.example.com/users?role=admin&active=true'

# 加 User-Agent 头 (有些接口检查 UA)
curl -A 'Mozilla/5.0' https://example.com/

# 加自定义请求头
curl -H 'Accept: application/json' https://api.example.com/users
curl -H 'X-Request-Id: abc123' https://api.example.com/users

几个高频参数:

4. POST/PUT/DELETE

# POST JSON
curl -X POST https://api.example.com/users \
  -H 'Content-Type: application/json' \
  -d '{"name":"Bob","email":"b@x.com"}'

# POST 表单 (-d 默认就是 application/x-www-form-urlencoded)
curl -X POST https://example.com/login \
  -d 'username=alice' \
  -d 'password=1234'

# POST 大段 JSON 用文件 (-d @filename)
curl -X POST https://api.example.com/users \
  -H 'Content-Type: application/json' \
  -d @payload.json

# -X 指定方法 (PUT/DELETE/PATCH)
curl -X DELETE https://api.example.com/users/42
curl -X PUT https://api.example.com/users/42 \
  -H 'Content-Type: application/json' \
  -d '{"name":"Bob II"}'

陷阱:在 URL 里写 & 必须给 URL 加引号,否则 shell 会把 & 当成后台执行符。

5. 文件上传与下载

# 上传单个文件 (multipart)
curl -X POST https://example.com/upload \
  -F 'file=@/path/to/avatar.png'

# 上传文件 + 其他字段
curl -X POST https://example.com/upload \
  -F 'title=我的头像' \
  -F 'file=@/path/to/avatar.png'

# 指定文件的 Content-Type
curl -X POST https://example.com/upload \
  -F 'file=@/path/to/data.csv;type=text/csv'

# 上传二进制 raw (-data-binary)
curl -X POST https://example.com/files \
  -H 'Content-Type: application/octet-stream' \
  --data-binary @/path/to/file.bin

# 下载文件 (等价 wget)
curl -O https://example.com/file.zip         # 保留原文件名
curl -o renamed.zip https://example.com/file.zip  # 改名

6. 认证

# HTTP Basic Auth
curl -u alice:secret https://api.example.com/me
# 等价于 -H 'Authorization: Basic YWxpY2U6c2VjcmV0'

# Bearer Token (JWT)
curl -H 'Authorization: Bearer eyJhbGciOi...' https://api.example.com/me

# 用环境变量避免泄露 Token (注意花括号要转义或加引号)
TOKEN='eyJhbGciOi...'
curl -H "Authorization: Bearer ${TOKEN}" https://api.example.com/me

# 让 curl 自动处理 "用户名密码" -> Basic Auth:
curl --netrc-file ~/.netrc https://api.example.com/me
# ~/.netrc 内容: machine api.example.com login alice password secret

用环境变量传 Token 时,双引号字符串才会展开变量,单引号不会。注意 shell 变量语法和 URL 模板字符串别混淆。

7. Cookie 处理

# 让 curl 保存服务器下发的 Cookie
curl -c cookies.txt https://example.com/login

# 后续请求带上 Cookie (实现"登录后再访问")
curl -b cookies.txt https://example.com/dashboard

# -c 和 -b 一起用: 保存 + 同时发送已有 Cookie
curl -b cookies.txt -c cookies.txt https://example.com/cart

# 手动指定 Cookie
curl -b 'sessionid=abc123; theme=dark' https://example.com/

-c + -b 是模拟"登录 → 访问受保护页面"流程的标准做法。两个一起用,session 期间持续更新。

8. HTTPS 调试

# 跳过证书验证 (调试自签名证书时用,生产别加!)
curl -k https://self-signed.example.com/

# 指定 CA 证书
curl --cacert /path/to/ca.pem https://api.example.com/

# 指定客户端证书 (mTLS 双向认证)
curl --cert client.pem --key client.key https://mtls.example.com/

# 强制用 TLS 1.3
curl --tlsv1.3 https://example.com/

# 看证书链
curl -v https://example.com/ 2>&1 | grep -E 'subject|issuer'

注意-k 跳过证书验证只能用于调试,生产脚本里千万别用——这等于关掉了 HTTPS 最大的安全保障。最常见合法用法是测试自签名证书的内网服务。

9. 代理

# 走 HTTP 代理
curl -x http://proxy.example.com:8080 https://target.com/

# 走 SOCKS5 代理
curl --socks5 host:1080 https://target.com/

# 用 Charles/Fiddler 抓 HTTPS 包时,代理 + 信任它的 CA
curl -x http://127.0.0.1:8888 \
  --cacert ~/Charles.crt \
  https://target.com/

# 用环境变量让所有 curl 请求走代理
export https_proxy=http://127.0.0.1:7890
curl https://www.google.com/

用 Charles / Fiddler / mitmproxy 抓 HTTPS 包时,标准流程:启动代理 → 信任 CA → curl 走代理 + 指定 CA

10. 性能与超时

# 限时 (-m 总秒数, --connect-timeout 连接超时)
curl --connect-timeout 5 -m 10 https://example.com/

# 一次请求的耗时分解 (DNS、TCP、TLS、首字节、总时长)
curl -o /dev/null -s -w '
DNS:        %{time_namelookup}s
TCP:        %{time_connect}s
TLS:        %{time_appconnect}s
FirstByte:  %{time_starttransfer}s
Total:      %{time_total}s
' https://example.com/

# 简单压测 (用 bash 循环,专业压测用 ab/wrk/k6)
for i in {1..100}; do
  curl -s -o /dev/null -w '%{http_code}\n' https://api.example.com/health &
done
wait

-w 的耗时分解特别适合排查慢请求——能立刻看出是 DNS 慢、TCP 慢、TLS 慢还是服务器响应慢。

11. -w 输出格式

# -w 输出变量 (常用)
%{http_code}              # 状态码
%{time_total}             # 总耗时
%{size_download}          # 下载字节数
%{url_effective}          # 实际 URL (跟随重定向后)
%{remote_ip}              # 目标服务器 IP
%{ssl_verify_result}      # 证书验证结果 (0 = OK)

# 实战: 只取状态码 (写脚本判断用)
code=$(curl -o /dev/null -s -w '%{http_code}' https://example.com/)
echo "状态码: ${code}"

12. 常用组合速查

13. curl vs wget

现代开发 90% 用 curl——因为它能精确控制每一个 header 和方法。

14. 进阶工具

小结

curl 三句话:看报文用 -v/-i,发数据用 -d/-F,调证书用 -k/--cacert。组合 -w + -o /dev/null 写脚本监控接口状态码是日常必备技巧。

← 上一篇 HTTPS 与 SSL/TLS

← 返回 HTTP 教程目录

✈️💬