
1. 项目概述为什么说curl是命令行里的“瑞士军刀”如果你在Linux或macOS的命令行里待过一段时间肯定会经常敲一个命令curl。它看起来平平无奇不就是个下载文件的工具吗但我要告诉你这个想法太低估它了。在我十多年的运维和开发经历里curl绝对是我工具箱里使用频率最高、也最被低估的命令行工具之一。它远不止是下载而是一个功能极其强大的HTTP客户端甚至可以说是命令行与网络世界交互的“万能接口”。简单来说curl是一个利用URL语法在命令行下工作的文件传输工具。它支持数十种协议从最常见的HTTP、HTTPS到FTP、SFTP甚至SCP、LDAP等几乎无所不包。但它的核心价值尤其在当今这个API驱动的时代在于处理HTTP/HTTPS请求。无论是快速测试一个API接口、调试一个诡异的网络问题、自动化下载资源还是作为脚本的一部分进行数据交互curl都能以最轻量、最直接的方式完成任务。为什么命令行高手都爱用curl因为它直接、高效、可脚本化。不需要打开笨重的浏览器开发者工具不需要启动Postman这类图形化客户端一个命令加上几个参数结果就清晰地打印在终端里。这种“所见即所得”的反馈速度对于调试和自动化来说是无可替代的。接下来我就结合自己踩过的无数坑和总结的经验为你拆解curl在HTTP/HTTPS场景下最实用、最高频的十种用法让你也能把这把“瑞士军刀”用得炉火纯青。2. 基础认知理解curl的核心工作模式与常用参数在深入具体用法之前我们需要统一一下对curl基础工作模式的理解。这能帮你更好地记忆参数而不是死记硬背。2.1 默认的“沉默”与“输出”curl默认的行为是将获取到的响应体Response Body直接输出到标准输出通常是你的终端屏幕。如果你只是curl https://example.com你会看到这个网页的HTML源代码哗啦啦地打印出来。这很直观但很多时候我们需要的不仅仅是响应体。一个新手常踩的坑是直接这样用curl测试API结果终端上一片混乱的JSON数据却看不到状态码、响应头等关键调试信息。所以第一个要养成的习惯就是在调试时永远加上-vverbose详细或-iinclude包含响应头选项。2.2 关键通用参数解析这些参数像乐高积木可以组合出各种功能-X, --request: 指定HTTP方法。虽然对于GET请求可以省略但明确指定是个好习惯例如-X GET、-X POST。-H, --header: 添加HTTP请求头。这是与API交互的灵魂格式为-H “Content-Type: application/json”。可以多次使用该参数添加多个头。-d, --data: 发送POST请求的数据体。这是最常用的发送数据的方式。-F, --form: 模拟表单提交multipart/form-data常用于上传文件。-o, --output: 将输出写入文件而不是标准输出。例如-o page.html。-O, --remote-name: 使用服务器上的文件名将输出保存到当前目录。-s, --silent: 静默模式。不显示进度条和错误信息。在脚本中非常有用可以避免无关输出污染结果。-v, --verbose: 详细模式。这是调试神器会输出整个通信过程包括请求头、响应头、SSL握手信息等。-i, --include: 在输出中包含HTTP响应头。-L, --location: 自动跟随重定向。如果服务器返回301/302等状态码curl会自动跳转到新的地址。-k, --insecure: 允许连接到使用自签名或无效证书的SSL站点。警告仅用于测试环境生产环境有安全风险。--connect-timeout/--max-time: 设置连接超时和最大请求时间对于控制脚本行为至关重要。理解了这些基础积木我们就可以开始搭建更复杂的应用场景了。3. 十种核心用法实战拆解下面这十种用法覆盖了从基础查询到高级调试的绝大部分日常场景。我会为每种用法提供经典命令示例并附上我的实操心得和避坑指南。3.1 用法一最基础的GET请求与内容获取这是curl的起手式用于获取一个URL的内容。经典命令curl https://api.github.com/users/octocat这个命令会向GitHub的API发起一个GET请求获取用户“octocat”的信息JSON格式并直接打印在终端。进阶与调试保存到文件curl -o octocat.json https://api.github.com/users/octocat查看完整通信过程调试必用curl -v https://api.github.com/users/octocat自动跟随重定向很多短链接服务会用到。curl -L http://short.url/abc实操心得直接用curl请求返回JSON的API时终端显示可能很乱。可以配合jq这个JSON处理工具使用curl -s https://api.github.com/users/octocat | jq .。-s参数用于静默模式避免进度条干扰jq的解析。3.2 用法二发送POST请求与提交JSON数据这是与RESTful API交互最核心的用法。关键在于正确设置Content-Type请求头。经典命令curl -X POST https://httpbin.org/post \ -H “Content-Type: application/json” \ -d ‘{“name”: “Alice”, “job”: “Engineer”}’这里-X POST指定方法。-H “Content-Type: application/json”告诉服务器我们发送的是JSON格式的数据。这个头经常被忘记导致服务器返回415 Unsupported Media Type错误。-d ‘{…}’是请求体数据。常见问题与排查数据从文件读取如果JSON很长可以写在文件里-d data.json。查看服务器返回了什么加上-i参数就能看到服务器返回的响应头和状态码比如HTTP/2 200。URL编码问题如果-d的参数是keyvaluekey2value2这种表单格式curl默认的Content-Type会是application/x-www-form-urlencoded。如果你需要发送这种格式但手动指定了JSON头就会出错。3.3 用法三模拟表单提交与文件上传当需要测试文件上传接口时-F参数就派上用场了。它会将请求编码为multipart/form-data。经典命令curl -X POST https://httpbin.org/post \ -F “usernamealice” \ -F “avatar/path/to/your/photo.jpg”这个命令模拟了一个包含用户名和头像文件的表单提交。符号告诉curl后面跟的是文件路径。实操心得-F和-d不要混用。一个请求要么是multipart/form-data(-F)要么是application/x-www-form-urlencoded或application/json(-d)。混用会导致行为未定义。你可以通过-F “file/path/to/file;typetext/plain”来手动指定文件的MIME类型。上传大文件时可以加上–limit-rate 500k来限制上传带宽避免打满网络。3.4 用法四管理HTTP请求头与认证信息HTTP头是控制请求行为的关键。除了Content-Type常见的还有认证头Authorization、用户代理User-Agent等。经典命令# 携带Bearer Token访问受保护API curl -H “Authorization: Bearer YOUR_ACCESS_TOKEN” \ https://api.example.com/protected-resource # 自定义User-Agent有时用于绕过简单的爬虫检测 curl -H “User-Agent: MyAwesomeClient/1.0” \ https://example.com # 同时设置多个头部 curl -H “Content-Type: application/json” \ -H “X-Custom-Header: MyValue” \ -X POST -d ‘{}’ https://api.example.com/endpoint认证方式汇总curl内置支持多种认证比手动写-H更方便Basic认证curl -u username:password https://example.comBearer Token如上所示手动加Authorization头是最清晰的方式。其他通过–negotiate、–ntlm等参数支持更复杂的认证方案。避坑指南在脚本中直接使用-u username:password会在进程列表里暴露密码。更安全的方式是使用-u username:然后让curl交互式提示输入密码或者从安全的环境变量中读取。3.5 用法五处理Cookie发送与保存会话对于需要登录会话的网站Cookie的管理至关重要。经典命令# 1. 模拟登录并将服务器返回的Cookie保存到文件 curl -c cookies.txt -X POST -d “useradminpass123456” https://example.com/login # 2. 使用保存的Cookie访问需要登录的页面 curl -b cookies.txt https://example.com/dashboard-c, --cookie-jar file: 将服务器返回的Set-Cookie头信息保存到指定文件。-b, --cookie data/file: 发送请求时携带Cookie数据。数据可以是namevalue字符串也可以是-c保存的文件。高级技巧你可以直接组合使用-b和-c让curl既发送旧的Cookie又保存新的Cookiecurl -b cookies.txt -c cookies.txt https://example.com/action。这非常适合模拟浏览器维持会话的过程。使用-v参数可以清楚地看到请求中发送的Cookie:头和响应中收到的Set-Cookie:头是调试登录问题的利器。3.6 用法六调试利器详细模式与只获取头信息当请求不符合预期时-v详细模式是你的第一道也是最重要的一道排查工具。经典命令curl -v https://httpbin.org/status/404运行这个命令你会看到类似下面的输出已简化* Trying 34.206.188.101:443... * Connected to httpbin.org (34.206.188.101) port 443 * TLSv1.3 (OUT), TLS handshake, Client hello (1): ... SSL握手信息 ... GET /status/404 HTTP/2 Host: httpbin.org User-Agent: curl/7.81.0 Accept: */* HTTP/2 404 date: Mon, 01 Jan 2024 00:00:00 GMT content-type: text/html; charsetutf-8 content-length: 0 * Connection #0 to host httpbin.org left intact开头的行是curl发送的请求头。开头的行是服务器返回的响应头。你可以清晰地看到我们用了HTTP/2协议服务器返回了404状态码。很多问题如认证失败401、权限不足403、参数错误400在这里一目了然。仅获取头信息有时你只关心资源的元信息比如文件大小、最后修改时间而不想下载整个文件。这时可以用-I大写i或–head参数它会让curl发送一个HEAD请求。curl -I https://example.com/large-file.zip响应会像这样HTTP/2 200 content-type: application/zip content-length: 1048576000 # 告诉你文件大小是1GB last-modified: Fri, 01 Jan 2024 12:00:00 GMT这对于检查链接是否有效、文件是否更新非常有用。3.7 用法七控制输出静默、限速与进度条curl默认会显示一个进度条这在交互时很好但在脚本中就成了“噪音”。-s, --silent:静默模式。不显示进度条、错误信息以外的任何内容。这是脚本编写的黄金搭档。-S, --show-error: 与-s配合使用。在静默模式下如果发生错误仍显示错误信息。通常组合为-sS。–limit-rate speed: 限制传输速率。例如–limit-rate 200k将速度限制在每秒200KB避免影响其他网络服务。-#, --progress-bar: 用简单的进度条代替默认的进度显示器。在日志中更清晰。脚本编写示例#!/bin/bash response$(curl -sS –max-time 10 https://api.example.com/health) if [ $? -eq 0 ]; then echo “API is healthy: $response” else echo “API health check failed!” fi这个脚本中-sS保证了输出的干净–max-time防止请求无限挂起$?获取curl的退出状态码0表示成功。3.8 用法八处理HTTPS与SSL证书问题在现代网络环境下HTTPS是标配。curl默认会验证服务器的SSL证书。但在测试环境如使用自签名证书的内部服务时这会造成麻烦。跳过证书验证仅用于测试curl -k https://internal-test-site.com。务必记住-k参数会使得中间人攻击成为可能绝不能在处理敏感数据的生产脚本中使用。指定自定义CA证书如果内部有私有CA可以用–cacert /path/to/ca-bundle.crt来指定信任的证书包。指定客户端证书有些双向TLSmTLS认证的服务需要客户端提供证书curl –cert client.pem –key client-key.pem https://secure-api.com。3.9 用法九构造复杂请求处理URL参数与数据GET请求的参数通常附在URL后面但手动拼接容易出错特别是参数需要编码时。直接拼接curl “https://api.example.com/search?qlinuxpage2”。注意URL最好用引号包裹防止shell将解释为后台运行。使用–data-urlencode(推荐)这个参数会自动对值进行URL编码。curl -G https://api.example.com/search \ –data-urlencode “qlinux command line” \ –data-urlencode “page2”-G参数表示将–data-urlencode产生的数据以?keyvalue…的形式附加到URL上从而构造一个GET请求。这样即使查询词包含空格或特殊字符也能被正确编码。POST发送x-www-form-urlencoded数据如果API要求POST方法但数据格式是application/x-www-form-urlencoded像传统HTML表单可以这样curl -X POST https://api.example.com/login \ -H “Content-Type: application/x-www-form-urlencoded” \ -d “usernamealicepasswordsecret”或者使用多个–data-urlencode参数curl会自动设置正确的Content-Type头curl -X POST https://api.example.com/login \ –data-urlencode “usernamealice” \ –data-urlencode “passwordsecret”3.10 用法十串联与管道将curl融入Shell工作流curl的真正威力在于它能无缝嵌入Shell管道Pipe与其他命令行工具如grep,jq,awk,sed) 协同工作实现强大的数据提取和自动化。经典组合示例从API获取JSON并提取特定字段curl -s https://api.github.com/repos/curl/curl/releases/latest | jq -r ‘.tag_name’这条命令获取curl项目最新发布版的标签名如curl-8_5_0并纯净地输出。检查网站标题是否包含特定关键词curl -s https://example.com | grep -i “title” | sed ‘s/[^]*//g’这条命令获取网页HTML过滤出包含title的行然后用sed去掉HTML标签只输出标题文本。下载文件并直接解压curl -sSL https://example.com/archive.tar.gz | tar -xz-L跟随重定向-sS静默但显示错误下载流直接通过管道传给tar解压无需在磁盘上创建临时文件。监控API端点状态while true; do if curl -sSf –max-time 5 https://api.example.com/health /dev/null; then echo “$(date): OK” else echo “$(date): FAILED” fi sleep 30 done这个简单的脚本每30秒检查一次API健康状态。-f(–fail) 参数让curl在HTTP错误码如404500时返回非0状态便于判断。终极心得把curl想象成网络请求的“标准输入/输出”。它从网络读取数据输出到标准输出。这个设计哲学使得它能与Unix哲学下的所有文本处理工具完美结合。当你习惯这种思维很多复杂的网络数据抓取和处理任务用一行管道命令就能优雅解决。4. 常见问题排查与实战技巧实录即使掌握了上述用法在实际操作中还是会遇到各种“坑”。下面是我总结的一些典型问题及解决方法。4.1 问题一请求超时或无响应现象命令卡住很久没反应最后可能报超时错误。排查步骤检查网络连通性先用ping或telnet检查目标主机和端口是否可达。telnet api.example.com 443。使用–connect-timeout和–max-time为curl设置合理的超时时间避免脚本无限等待。例如–connect-timeout 10 –max-time 30。使用-v查看卡在哪一步详细输出会显示Trying IP…、Connected to…、TLS handshake…等阶段卡在哪一行就很清楚。检查DNS如果Trying IP…这一步很久可能是DNS解析慢。可以尝试使用–resolve参数绕过DNScurl –resolve api.example.com:443:192.0.2.1 https://api.example.com。4.2 问题二返回奇怪的错误码如400 401 403 404 502400 Bad Request这是客户端错误说明你的请求格式有问题。立刻使用-v查看你发送的请求头和数据体。99%的原因在于Content-Type头与-d或-F的数据格式不匹配。JSON数据格式错误缺少引号或括号。URL或参数未正确编码。尝试用–data-urlencode。401 Unauthorized缺少或错误的认证信息。检查Authorization头或-u参数。Token是否过期密码是否正确403 Forbidden认证通过但权限不足。检查使用的账号是否有访问该资源的权限。404 Not FoundURL路径错误。仔细检查API文档确认端点路径。使用-v看最终发送的完整URL。502 Bad Gateway/503 Service Unavailable这是服务器端或网关错误客户端通常无法直接解决。可以重试几次使用脚本循环。检查是否是服务器维护或过载。如果是反向代理如Nginx报502可能是后端服务挂了。4.3 问题三SSL证书验证失败错误信息curl: (60) SSL certificate problem: self-signed certificate或unable to get local issuer certificate。解决方案测试环境使用-k跳过验证。仅限测试生产/内网环境获取服务器的自签名证书或内部CA的根证书。使用–cacert参数指定该证书文件curl –cacert /etc/ssl/my-ca.pem https://internal.service。或者将CA证书添加到系统默认的证书存储路径操作较复杂需根据系统而定。4.4 问题四从浏览器复制cURL命令现代浏览器Chrome/Firefox开发者工具的“Network”标签右键点击请求可以选择“Copy as cURL”。这是一个极其强大的功能能一键复制出包含所有头信息、Cookie、数据的复杂curl命令用于重现浏览器请求。这是逆向工程和调试的终极利器。使用技巧复制出来的命令可能很长包含很多浏览器特有的头如sec-ch-ua。你可以安全地删除其中一些非必要的头来简化命令但通常保留Cookie、Authorization、Content-Type等关键头即可。4.5 性能与脚本优化技巧复用连接默认情况下curl每次请求都会新建TCP连接。对于需要连续调用同一API的脚本可以使用–keepalive-time参数尝试保持连接但更常见的优化是在脚本层面控制频率或使用专门的HTTP客户端库。并行下载curl本身是单线程的。如果需要并行下载多个文件可以结合xargs或GNU parallel工具或者使用wget的-i输入文件功能。输出到变量在Bash脚本中使用$(curl …)将输出捕获到变量中。记得总是加上-sS参数。处理压缩内容如果服务器返回gzip压缩的内容curl会原样输出乱码。你可以手动添加-H “Accept-Encoding: gzip”头但curl不会自动解压。通常的流程是服务器根据这个头决定是否压缩如果压缩了你需要用其他工具如gunzip处理。更好的方式是让服务器返回未压缩的内容或者使用能自动解压的编程语言HTTP库。掌握这十种用法和排错技巧你就能用curl应对日常开发、运维、测试中绝大多数与HTTP相关的任务。它可能不是解决所有网络问题的唯一工具但一定是那个最快、最直接、最可靠的选择。下次遇到需要测试接口、抓取数据、调试网络的时候别急着打开图形化工具先试试在命令行里敲一个curl你会发现很多问题变得如此清晰和简单。