这个命令是干啥的
curl 全称是 Client URL,说白了就是一个用 URL 语法传数据的命令行工具。它支持 HTTP、HTTPS、FTP、SFTP 等一堆协议。在运维和开发的世界里,curl 就是你的瑞士军刀。
我刚开始接触 Linux 那会,遇到个场景:后端同事说"接口通了",我这边用浏览器发请求发现连不上。他说"你用 curl 试试",我一脸懵。后来学会了 curl,才发现之前那些"装 Postman"、"写 Python requests"的操作,大部分时候一行 curl 就搞定了。
curl 能做的事情包括但不限于:调接口看返回、下载文件、看响应头、模拟 POST 提交表单、测接口响应时间、断点续传。一个命令,顶半个工具箱。
基本用法(3分钟上手)
最简单的 GET 请求
# 直接发 GET 请求,把返回内容打出来
curl https://api.github.com
默认情况下 curl 会把响应体打印到终端,而且会显示进度条(如果是下载的话)。如果你觉得进度条碍眼,加 -s 静默模式就好。
保存响应到文件
# 把接口返回的内容保存到本地文件
curl -o result.json https://api.example.com/users
-o 就是 output 的意思,后面跟文件名。这个比用 > 重定向更稳,因为 curl 的进度条和错误信息不会混进去。
查看详细信息
# 显示请求和响应的完整信息,包括 HTTP 头、TLS 握手过程
curl -v https://www.baidu.com
-v 是我的最爱。它能让你看到整个 HTTP 对话过程:DNS 解析、TCP 连接、TLS 握手、请求头、响应头。接口调不通的时候,第一件事就是 -v 看看。
进阶骚操作
指定 HTTP 方法和请求头
# 用 POST 方法,带自定义请求头发请求
curl -X POST https://api.example.com/login \
-H "Content-Type: application/json" \
-H "Authorization: Bearer token123" \
-d '{"username":"admin","password":"123456"}'
-X 指定 HTTP 方法,-H 加请求头,-d 传请求体。注意加了 -d 之后,curl 会自动把方法变成 POST,所以有时候 -X POST 可以省略。
但有个坑:如果你的 -d 数据里包含特殊字符(比如中文、空格、& 符号),最好用 --data-urlencode 替代:
# URL 编码方式传参,不用自己手动编码
curl --data-urlencode "name=张三" --data-urlencode "city=上海" https://api.example.com/form
跟随重定向
# 允许 curl 自动跟随 301/302 跳转
curl -L http://example.com
不加 -L 的话,curl 碰到 302 就直接返回跳转响应,不会跟着走。用 -L 最多能跟 50 次,防止死循环。
查看响应头
# 只看响应头,不看响应体
curl -I https://www.baidu.com
-I 发的是 HEAD 请求,只拿头不拿体。想看响应头又不想改请求方法,可以用:
# 既看响应头又看响应体,用 -i 或者 -v
curl -i https://www.baidu.com
-i 把响应头和响应体一起打印,-v 更详细包括请求过程。
统计请求耗时
# 请求结束后打印各阶段耗时统计
curl -w "\n\n时间统计:\ntime_namelookup: %{time_namelookup}s\ntime_connect: %{time_connect}s\ntime_starttransfer: %{time_starttransfer}s\ntime_total: %{time_total}s\n" -o /dev/null -s https://www.baidu.com
这个 -w 参数特别好用。它能告诉你 DNS 解析花了多久、TCP 连接多久、首字节多久、总共多久。排查接口慢的问题,这招比啥都直观。
我一般会把常用格式写成文件:
# 写一个 curl-format.txt 文件
echo -e "time_namelookup: %{time_namelookup}s\ntime_connect: %{time_connect}s\ntime_appconnect: %{time_appconnect}s\ntime_starttransfer: %{time_starttransfer}s\ntime_total: %{time_total}s\n" > curl-format.txt
# 然后引用这个文件
curl -w @curl-format.txt -o /dev/null -s https://www.baidu.com
断点续传下载
# 文件下载到一半断开了?加 -C - 自动续传
curl -C - -o bigfile.iso https://example.com/bigfile.iso
-C - 是自动续传,curl 会检测本地已有文件的大小,从断点继续下载。下大文件的时候必加这个参数,不然断了重下几十个 G 的包真的会崩溃。
避坑指南
1. SSL 证书错误
# 跳过 SSL 证书验证(生产环境不要用!)
curl -k https://self-signed.example.com
自签名证书的内网服务,curl 默认会报 SSL 错误。-k 能跳过验证,但只是临时排查用,别写进生产脚本。
更好的做法是把证书加进去:
# 指定 CA 证书文件
curl --cacert /path/to/ca.crt https://internal.example.com
2. 大文件下载被中断
下载大文件一定要加 -C - 和 -L,而且注意磁盘空间。我踩过一个大坑:下载了几个 G 的日志包,结果 /tmp 满了,curl 直接报错退出。
3. -d 和 -X 的微妙关系
# 这行加了 -X GET,但 -d 还在,实际会变成 POST
curl -X GET -d "name=test" http://example.com/api
-X 会覆盖默认方法,但 -d 的存在会让 curl 加上 Content-Type: application/x-www-form-urlencoded 并发送请求体,实际上服务端收到的是 POST。这个坑我栽过好几次。
4. Cookie 处理
# 保存 Cookie 并后续使用
curl -c cookies.txt -b cookies.txt https://example.com/login
curl -b cookies.txt https://example.com/dashboard
-c 是写 cookie 文件,-b 是读 cookie 文件。很多登录态的接口调试要用到。
实战场景
场景一:接口健康检查脚本
公司有一套微服务,大家经常说某个服务挂了,但其实只是他们的网络有问题。我写了个脚本定期测:
#!/bin/bash
# 健康检查脚本,检查服务是否正常
services=(
"https://api.example.com/health"
"https://order.example.com/health"
"https://user.example.com/health"
)
for url in "${services[@]}"; do
# 发请求检查,超时设 5 秒,只看响应头
http_code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 "$url")
if [ "$http_code" = "200" ]; then
echo "[OK] $url -> $http_code"
else
echo "[FAIL] $url -> $http_code"
fi
done
场景二:测接口响应时间
新版本上线后接口变慢了,用 curl 的 -w 参数批量测试:
#!/bin/bash
# 批量测试多个接口的响应时间
urls=(
"https://api.example.com/users"
"https://api.example.com/orders"
"https://api.example.com/products"
)
# 定义耗时统计格式
fmt="%{http_code}\t%{time_total}\t%{url_effective}\n"
echo -e "状态码\t总耗时\tURL"
for url in "${urls[@]}"; do
# 发 3 次取平均值
total=0
for i in 1 2 3; do
t=$(curl -s -o /dev/null -w "%{time_total}" "$url")
total=$(echo "$total + $t" | bc)
done
avg=$(echo "scale=3; $total / 3" | bc)
echo "接口: $url 平均耗时: ${avg}s"
done
场景三:上传文件到图床
# 用 POST 上传文件,等价于 multipart/form-data
curl -F "file=@/path/to/photo.jpg" -F "type=avatar" https://upload.example.com/api
-F 是模拟表单上传文件,@ 后面跟文件路径。多个字段就写多个 -F。
场景四:断网排查
线上服务器连不上外网,ping 不通,nslookup 能解析,怎么办?
# 用 -v 看具体卡在哪一步
curl -v --connect-timeout 5 https://www.baidu.com
看输出:
- 如果卡在 Trying xxx.xxx.xxx.xxx -> 网络不通,防火墙或路由问题
- 如果卡在 SSL connection -> TLS 握手问题
- 如果返回了内容但很慢 -> DNS 或带宽问题
今日作业
用 curl 写一个脚本,检查你的博客或公司网站是否正常运行,要求:
1. 检查 HTTP 状态码是否为 200
2. 如果状态码不是 200,重试 3 次,每次间隔 2 秒
3. 打印每次检查的响应时间和最终结果
4. 超时设置为 10 秒
提示:用 --retry、--retry-delay、--connect-timeout 这些参数组合一下就能实现。