curl 详解:命令行下的 HTTP 瑞士军刀
测一个接口、下一个文件、查一个响应头——在命令行里完成这些事的默认答案几乎都是同一条命令:curl。它由 Daniel Stenberg 于 1998 年发起,如今支持 HTTP/HTTPS、FTP、SMTP 等 20+ 协议,被内置进 macOS、Linux、Windows 10 及几乎所有发行版,官网 curl.se,源码托管于 curl/curl,约 37k Star。本文从核心概念、常用用法、进阶技巧到排查实践,完整拆解。
1、项目概述
curl 是一个命令行传输工具与库(libcurl),口号是 "command line tool and library for transferring data with URLs"。底层库 libcurl 被几乎所有语言与框架绑定(PHP 的 cURL、Python 的 pycurl、Go 的默认 HTTP 抓取等),命令行工具则通过参数直接驱动。
基本形态与协议:
- 语法:curl [options] URL,URL 是第一公民,一切围绕 URL 展开
- 协议:HTTP/HTTPS/HTTP2/HTTP3、FTP/SFTP、SMTP/IMAP、WebSocket 等 20+
- 协议为 MIT 类似的 curl license,可自由商用与嵌入
- 兄弟项目:wget 偏"下载器",curl 偏"请求构造器",定位不同
2、四大核心能力
curl 的能力可以归成四根支柱,覆盖命令行网络交互的主要环节。
四根支柱:
- 请求构造:自定义方法、头、体、认证,完整模拟任意 HTTP 请求
- 数据传输:上传(-T/-d/--form)、下载(-O/-o)、断点续传(-C -)
- 调试观测:-v 详细交互、-w 自定义统计、--trace 时间线抓取
- 连接控制:代理、超时、重试、DNS 指定、TLS 证书校验开关
能力要点:
1. 无状态单次执行:不保存 Cookie 到磁盘(除非 -c/-b),适合脚本化
2. 参数即文档:man curl 超过 4000 行,每个能力都有独立开关
3. 浏览器"复制为 cURL"功能让请求可脱离前端直接复现
3、基础用法:请求与响应
最常用的场景:GET 请求、下载文件、指定方法与请求体。
# GET 请求(默认)
curl https://api.example.com/users
# 带 URL 参数的 GET
curl "https://api.example.com/search?q=curl&page=2"
# POST JSON
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d '{"name":"alice","age":18}'
# 下载文件(保留远端文件名 / 指定文件名)
curl -O https://example.com/app.zip
curl -o my.zip https://example.com/app.zip基础要点:
1. 多个查询参数的 URL 务必加引号,防止 & 被 shell 解析为后台执行
2. -d 会自动把方法切为 POST,-X POST 可省
3. -d 默认 Content-Type 为 form 表单,发 JSON 需手动 -H 指定
4. -F 上传文件走 multipart:curl -F "file=@photo.jpg" URL
4、认证与请求头
真实接口几乎都有认证与自定义头,curl 对此有一整套开关。
# Bearer Token(最常见)
curl -H "Authorization: Bearer eyJhbGciOi..." https://api.example.com/me
# Basic Auth(用户名密码)
curl -u alice:secret https://api.example.com/admin
# 自定义请求头 + User-Agent 伪装
curl -H "X-Api-Key: 123456" \
-A "MyApp/1.0" \
https://api.example.com/data
# 从文件读请求体
curl -X PUT https://api.example.com/config -d @body.json认证要点:
1. Token 建议放环境变量再拼接,避免明文进 shell 历史
2. @文件名 语法同样适用于 -d,大请求体从文件读取更稳妥
3. -H 可重复使用叠加多个头;-A 是 -H "User-Agent: ..." 的简写
5、调试与观测
排查接口问题时,curl 的观测能力往往比图形化工具更直接。
# 查看完整交互过程(请求头+响应头)
curl -v https://api.example.com/users
# 只输出响应头
curl -I https://api.example.com/
# 自定义统计:状态码、耗时、下载大小
curl -o /dev/null -s -w "code=%{http_code} dns=%{time_namelookup}s total=%{time_total}s\n" \
https://api.example.com/
# 跟随重定向
curl -L http://example.com观测要点:
1. -v 输出中 ">" 开头是发出的请求、"<" 是收到的响应
2. -w 的 %{time_namelookup}/%{time_connect}/%{time_total} 可拆解各阶段耗时
3. -s 静默进度条,常与 -o /dev/null 配合做纯测速
4. --trace-time 加时间戳,适合对比多次请求
6、进阶技巧:代理、重试与续传
脚本化与弱网环境下,连接控制类参数是稳定性的关键。
# 设置代理(含 SOCKS5)
curl -x http://127.0.0.1:7890 https://api.example.com
curl -x socks5h://127.0.0.1:1080 https://api.example.com
# 超时 + 失败重试
curl --connect-timeout 5 --max-time 30 --retry 3 --retry-delay 2 URL
# 断点续传(续传大文件)
curl -C - -O https://example.com/big.iso
# 忽略自签名证书(仅调试用)
curl -k https://self-signed.example.com进阶要点:
1. socks5h 的 h 表示域名解析也走代理,防 DNS 泄露
2. --retry 默认只对临时错误(5xx、超时)生效,加 --retry-all-errors 扩大范围
3. -C - 配合 -O 可反复执行直到下载完成,适合大文件弱网
4. -k 关闭证书校验有中间人风险,禁止在生产脚本使用
7、定位对比:工具三选一
把 curl 与 wget、HTTPie 放在一张桌上,各自的位置清晰起来。
三者对比:
- curl:请求构造器,协议最全、参数最细,脚本与 CI 的事实标准
- wget:下载器,递归抓站、断点续传开箱即用,交互请求能力弱
- HTTPie:人类友好,默认 JSON 高亮与简洁语法,但依赖 Python 安装
选型建议:
1. 调接口、写脚本、CI 健康检查 → curl
2. 批量下载整站资源 → wget
3. 日常手敲 JSON 接口想要好读的输出 → HTTPie
4. 组合玩法:浏览器 DevTools 复制为 cURL,粘到命令行改造后回放
8、总结
curl 是命令行网络交互的事实标准(约 37k Star、20+ 协议、全平台内置):以"URL 第一"的模型统一了请求构造、数据传输、调试观测与连接控制四类能力,从一行 GET 到复杂的重试续传脚本都能覆盖;底层 libcurl 更是被几乎所有语言绑定,学一套参数即全栈通用。
落地建议:把 -v、-H、-d、-o、-w、-L 这六个高频参数练熟即可应对八成日常;调试时用 -w 拆解耗时、用 -C - 续传大文件;写进脚本时务必补齐超时与重试,杜绝裸奔请求。对于任何需要与网络接口打交道的开发者与运维,curl 是必要的随身工具。

