1. 初识curl:网络数据传输的瑞士军刀
第一次接触curl是在2007年调试一个API接口时。当时我正苦恼于如何快速测试HTTP请求,同事扔给我一行curl命令,瞬间解决了问题。curl(Client URL)这个开源的命令行工具,就像一把网络数据传输的瑞士军刀,能在没有图形界面的环境下完成各种网络请求操作。它支持包括HTTP、HTTPS、FTP、FTPS、SCP、SFTP等在内的数十种协议,几乎覆盖了所有常见的数据传输场景。
在Linux服务器上排查问题时,curl往往是唯一可用的工具;在自动化脚本中,curl因其稳定性和灵活性成为首选;甚至在日常开发中,我也习惯先用curl快速验证接口,再着手编写正式代码。经过15年的使用,我整理出这份最完整的curl指南,涵盖从基础到高阶的所有实用技巧。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础使用:从零开始掌握curl
2.1 安装与版本检查
大多数Linux发行版和macOS都预装了curl。检查是否安装及版本信息:
bash复制curl --version
如果未安装,各系统的安装命令如下:
- Ubuntu/Debian:
sudo apt install curl - CentOS/RHEL:
sudo yum install curl - macOS: 自带或通过
brew install curl获取最新版 - Windows: 下载官方二进制或通过Chocolatey安装
提示:生产环境建议使用较新版本(7.29.0以上),老版本可能缺少重要特性或存在安全漏洞。
2.2 最简单的GET请求
发起GET请求只需指定URL:
bash复制curl https://example.com
这个命令会:
- 解析URL中的协议(https)和域名
- 默认使用80/443端口
- 将响应体直接输出到终端
2.3 控制输出与保存结果
默认输出到终端,如需保存到文件:
bash复制curl -o output.html https://example.com
或者让curl自动根据URL生成文件名:
bash复制curl -O https://example.com/index.html # 保存为index.html
查看详细请求过程(调试时特别有用):
bash复制curl -v https://example.com
3. 进阶请求:处理各种HTTP场景
3.1 POST请求与数据发送
发送表单数据(Content-Type: application/x-www-form-urlencoded):
bash复制curl -d "user=admin&password=123456" https://example.com/login
发送JSON数据(需指定Content-Type):
bash复制curl -H "Content-Type: application/json" \
-d '{"username":"admin","password":"123456"}' \
https://example.com/api/login
上传文件(multipart/form-data):
bash复制curl -F "file=@/path/to/local/file" https://example.com/upload
3.2 处理HTTP头部信息
查看响应头(-I/--head):
bash复制curl -I https://example.com
自定义请求头:
bash复制curl -H "Authorization: Bearer token123" \
-H "X-Custom-Header: value" \
https://example.com/api
3.3 处理Cookie与会话
保存服务器返回的Cookie到文件:
bash复制curl -c cookies.txt https://example.com/login
后续请求携带Cookie:
bash复制curl -b cookies.txt https://example.com/dashboard
3.4 处理重定向
默认不跟随重定向,使用-L自动跟随:
bash复制curl -L https://example.com/redirect
限制最大重定向次数(防止无限循环):
bash复制curl -L --max-redirs 3 https://example.com/redirect
4. 高级技巧:解决实际问题
4.1 调试与性能分析
显示请求时间统计:
bash复制curl -w "DNS解析: %{time_namelookup}\n连接建立: %{time_connect}\nSSL握手: %{time_appconnect}\n首字节: %{time_starttransfer}\n总时间: %{time_total}\n" \
https://example.com
输出格式说明:
- time_namelookup: DNS解析耗时
- time_connect: TCP连接建立耗时
- time_appconnect: SSL/TLS握手耗时(HTTPS)
- time_starttransfer: 从请求开始到收到第一个字节的时间
- time_total: 总耗时
4.2 断点续传与限速
继续未完成的下载:
bash复制curl -C - -O https://example.com/largefile.zip
限制下载速度(防止占用全部带宽):
bash复制curl --limit-rate 200K -O https://example.com/largefile.zip
4.3 代理与网络配置
通过代理服务器访问:
bash复制curl -x http://proxy.example.com:8080 https://target.example.com
指定本地网络接口(多网卡环境):
bash复制curl --interface eth1 https://example.com
4.4 证书与SSL验证
跳过SSL证书验证(仅测试环境使用):
bash复制curl -k https://example.com
指定自定义CA证书:
bash复制curl --cacert /path/to/ca.pem https://example.com
使用客户端证书:
bash复制curl --cert client.pem --key key.pem https://example.com
5. 实战场景:curl在开发运维中的应用
5.1 API测试与调试
测试RESTful API的完整流程:
bash复制# 1. 获取认证token
token=$(curl -s -X POST \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"123456"}' \
https://api.example.com/auth/login | jq -r '.token')
# 2. 使用token获取用户信息
curl -H "Authorization: Bearer $token" \
https://api.example.com/users/me
# 3. 创建资源
curl -X POST \
-H "Authorization: Bearer $token" \
-H "Content-Type: application/json" \
-d '{"name":"New Item"}' \
https://api.example.com/items
# 4. 更新资源
curl -X PUT \
-H "Authorization: Bearer $token" \
-H "Content-Type: application/json" \
-d '{"name":"Updated Item"}' \
https://api.example.com/items/123
# 5. 删除资源
curl -X DELETE \
-H "Authorization: Bearer $token" \
https://api.example.com/items/123
5.2 服务器监控与健康检查
编写监控脚本检查服务状态:
bash复制#!/bin/bash
response=$(curl -s -o /dev/null -w "%{http_code}" https://example.com/health)
if [ "$response" -eq 200 ]; then
echo "服务正常"
else
echo "服务异常,状态码: $response"
# 发送告警...
fi
5.3 批量下载与自动化
下载多个文件:
bash复制curl -O https://example.com/files/file1.zip \
-O https://example.com/files/file2.zip \
-O https://example.com/files/file3.zip
或者从文件列表批量下载:
bash复制while read url; do
curl -O "$url"
done < urls.txt
5.4 与jq配合处理JSON响应
解析JSON响应并提取特定字段:
bash复制curl -s https://api.example.com/users | jq '.[] | select(.age > 30) | .name'
这个命令会:
- 静默请求API(-s)
- 使用jq处理JSON
- 筛选年龄大于30的用户
- 只输出用户名
6. 常见问题与解决方案
6.1 乱码问题处理
强制指定响应编码(如UTF-8):
bash复制curl -H "Accept-Charset: utf-8" https://example.com
或者转换编码:
bash复制curl https://example.com | iconv -f gbk -t utf-8
6.2 连接超时设置
设置各种超时参数:
bash复制curl --connect-timeout 5 \ # 连接超时5秒
--max-time 10 \ # 整个请求最多10秒
--retry 3 \ # 失败重试3次
--retry-delay 2 \ # 每次重试间隔2秒
https://example.com
6.3 大文件下载优化
使用压缩传输(如果服务器支持):
bash复制curl --compressed -O https://example.com/largefile
分块下载后合并:
bash复制curl -r 0-999999 -o part1 https://example.com/largefile
curl -r 1000000-1999999 -o part2 https://example.com/largefile
cat part1 part2 > largefile
6.4 认证与OAuth2.0流程
Basic认证:
bash复制curl -u username:password https://example.com
OAuth2.0密码模式:
bash复制# 获取token
token=$(curl -s -X POST \
-u "client_id:client_secret" \
-d "grant_type=password&username=user&password=pass" \
https://auth.example.com/token | jq -r '.access_token')
# 使用token访问API
curl -H "Authorization: Bearer $token" https://api.example.com/data
7. 性能优化与最佳实践
7.1 连接复用与HTTP/2
启用连接复用(减少TCP握手开销):
bash复制curl --http1.1 --keepalive-time 60 https://example.com
尝试使用HTTP/2(如果服务器支持):
bash复制curl --http2 https://example.com
7.2 并行请求与多路复用
使用xargs实现简单并行下载:
bash复制cat urls.txt | xargs -n1 -P4 curl -O
这个命令会:
- 从urls.txt读取URL列表
- 每个URL作为一个参数(-n1)
- 同时最多4个进程(-P4)
- 每个URL使用curl下载
7.3 缓存控制与条件请求
使用ETag/Last-Modified实现条件请求:
bash复制# 第一次请求,保存ETag和Last-Modified
curl -I https://example.com/resource > headers.txt
# 后续请求,使用保存的条件头
etag=$(grep -i 'ETag:' headers.txt | cut -d' ' -f2 | tr -d '\r')
last_modified=$(grep -i 'Last-Modified:' headers.txt | cut -d' ' -f2- | tr -d '\r')
curl -H "If-None-Match: $etag" \
-H "If-Modified-Since: $last_modified" \
https://example.com/resource
7.4 编写可维护的curl脚本
将复杂curl命令封装为函数:
bash复制api_request() {
local method=$1
local path=$2
local data=$3
curl -s -X "$method" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d "$data" \
"https://api.example.com/$path"
}
# 使用示例
API_TOKEN="your_token"
api_request GET "users/me"
api_request POST "items" '{"name":"New Item"}'
8. 安全注意事项
8.1 敏感信息处理
不要在命令行直接暴露密码/密钥:
bash复制# 不安全的方式(会出现在历史记录和进程列表中)
curl -u username:password https://example.com
# 更安全的方式
read -s -p "Password: " password
curl -u username:"$password" https://example.com
unset password
或者使用.netrc文件(~/.netrc):
code复制machine example.com
login username
password secret
然后设置文件权限:
bash复制chmod 600 ~/.netrc
8.2 输入验证与脚本安全
处理URL参数时进行验证:
bash复制#!/bin/bash
url="$1"
# 验证URL格式
if [[ ! "$url" =~ ^https?:// ]]; then
echo "错误:URL必须以http://或https://开头" >&2
exit 1
fi
# 限制允许的域名
if [[ ! "$url" =~ @(example.com|api.example.com) ]]; then
echo "错误:不允许的域名" >&2
exit 1
fi
curl "$url"
8.3 日志与审计
记录curl请求的完整信息:
bash复制log_curl() {
local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
local cmd="$*"
echo "[$timestamp] 执行: $cmd" >> /var/log/curl_audit.log
# 执行并记录输出
"$@" | tee -a /var/log/curl_audit.log
}
# 使用示例
log_curl -H "Authorization: Bearer $TOKEN" https://api.example.com/sensitive
8.4 更新与漏洞防范
定期检查并更新curl版本:
bash复制# 检查已知漏洞
curl --version | grep -q '7.64.0' && echo "警告:此版本存在已知漏洞"
# 各系统更新方法
# Ubuntu/Debian:
sudo apt update && sudo apt upgrade curl
# CentOS/RHEL:
sudo yum update curl
# macOS (Homebrew):
brew upgrade curl
9. 与其他工具的集成
9.1 结合awk/grep处理输出
提取特定HTTP头:
bash复制curl -I https://example.com | grep -i '^content-type:'
统计网页中特定单词出现次数:
bash复制curl -s https://example.com | grep -o -i 'word' | wc -l
9.2 与Postman的转换
将Postman请求转换为curl命令:
- 在Postman中选择请求
- 点击"Code"按钮
- 选择"cURL"格式
也可以使用Postman的CLI工具newman运行curl生成的集合。
9.3 在Python中调用curl
通过subprocess模块:
python复制import subprocess
result = subprocess.run(['curl', '-s', 'https://example.com'],
capture_output=True, text=True)
print(result.stdout)
或者使用pycurl库(curl的Python绑定):
python复制import pycurl
from io import BytesIO
buffer = BytesIO()
c = pycurl.Curl()
c.setopt(c.URL, 'https://example.com')
c.setopt(c.WRITEDATA, buffer)
c.perform()
c.close()
print(buffer.getvalue().decode('utf-8'))
9.4 在JavaScript中生成curl命令
前端调试时生成curl命令:
javascript复制function generateCurl(method, url, headers, data) {
let curl = `curl -X ${method} '${url}'`;
for (const [key, value] of Object.entries(headers)) {
curl += ` \\\n -H '${key}: ${value}'`;
}
if (data) {
curl += ` \\\n -d '${JSON.stringify(data).replace(/'/g, "\\'")}'`;
}
return curl;
}
// 使用示例
const curlCommand = generateCurl(
'POST',
'https://api.example.com/login',
{
'Content-Type': 'application/json',
'Accept': 'application/json'
},
{
username: 'admin',
password: '123456'
}
);
console.log(curlCommand);
10. 个人经验与实用技巧
10.1 调试复杂请求的秘诀
使用--trace或--trace-ascii记录完整通信:
bash复制curl --trace trace.log https://example.com
这个文件会包含所有发送和接收的原始数据,包括SSL握手过程。当遇到难以理解的问题时,这是最强大的调试工具。
10.2 处理特殊字符的坑
URL中的特殊字符需要正确编码。我发现最容易出问题的是:
bash复制# 错误:&会被shell解释
curl https://example.com/search?q=foo&sort=desc
# 正确:引号包裹或编码
curl "https://example.com/search?q=foo&sort=desc"
curl https://example.com/search?q=foo%26sort%3Ddesc
JSON数据中的单引号也需要特别注意:
bash复制# 错误:JSON中的单引号与shell引号冲突
curl -d '{"name":"O'Reilly"}' https://example.com
# 正确:转义或使用双引号
curl -d '{"name":"O'\''Reilly"}' https://example.com
curl -d "{\"name\":\"O'Reilly\"}" https://example.com
10.3 性能调优实战经验
经过多次性能测试,我发现这些参数对速度影响最大:
bash复制curl \
--compressed \ # 启用压缩
--http2 \ # 使用HTTP/2
--tcp-fastopen \ # 启用TCP Fast Open
--resolve example.com:443:1.2.3.4 \ # 跳过DNS解析
https://example.com
在延迟高的网络环境中,这些优化可以显著减少请求时间。
10.4 最有用的别名配置
我的~/.bashrc中这些别名节省了大量时间:
bash复制# 快速查看HTTP头
alias curli='curl -I'
# 跟随重定向并显示详细信息
alias curlf='curl -L -v'
# 下载并显示进度条
alias curlp='curl --progress-bar -O'
# 测试API响应时间
alias curlt='curl -w "\n时间统计:\n总时间: %{time_total}\nDNS: %{time_namelookup}\n连接: %{time_connect}\nSSL: %{time_appconnect}\n首字节: %{time_starttransfer}\n" -o /dev/null -s'
# 快速测试gzip压缩效果
alias curlgz='curl -H "Accept-Encoding: gzip" -I'
10.5 最常遇到的5个错误及解决
-
SSL证书验证失败:
bash复制curl: (60) SSL certificate problem: unable to get local issuer certificate解决方案:使用
--cacert指定证书或-k跳过验证(仅测试环境) -
连接被拒绝:
bash复制
curl: (7) Failed to connect to example.com port 443: Connection refused检查:防火墙、服务是否运行、端口是否正确
-
超时:
bash复制
curl: (28) Operation timed out after 3000 milliseconds with 0 bytes received增加
--connect-timeout和--max-time值 -
HTTP错误:
bash复制
curl: (22) The requested URL returned error: 401 Unauthorized检查认证信息是否正确
-
内存不足:
bash复制
curl: (23) Failed writing body (xxxx != yyyy)使用
-o将输出重定向到文件而不是内存
