返回博客

什么是 cURL 命令?它是如何工作的?

-
Understanding cURL cover
目录
-

核心要点

  • cURL 可帮助您在任意两个 URL 之间传输数据。
  • 它在 Windows、macOS 和 Linux 上的使用方式相同。
  • 您可以使用 cURL 测试 API、自动提交表单、下载文件,以及排查连接问题。

cURL 是 Client URL 的缩写,是一种远没有得到应有关注的工具。或许是因为它低调内敛,总是默默在后台工作。但正如您所知,cURL 是在 URL 之间传输数据最简单、最强大的方式之一。

无论您使用哪种协议、处于哪个平台、想要完成什么任务,只要数据在网络上,cURL 总能想办法搞定。本文将为您详细介绍它的使用方法。

cURL 是什么?

cURL 是一种命令行工具,最初是为了解决一个实际问题而诞生的。1996年,瑞典开发者 Daniel Stenberg 正在开发一个互联网中继聊天(IRC)机器人,他需要一种方法从网络上获取实时汇率数据,并将其发送到聊天对话中。

他找到了一个起点:httpget,这是巴西开发者 Rafael Sagula 最初编写的一款命令行工具。Daniel 在此基础上不断扩展、重写并持续更新。在接下来的几年里,他成为该项目的核心维护者,陆续加入了对更多协议的支持、更完善的传输处理,以及跨平台的稳定性。

这款工具几经更名,最终定名为 cURL,即“Client URL”的缩写。这个名字沿用至今,因为它恰如其分。从那以后,cURL 悄然成为了互联网基础设施的一部分。如果您曾好奇 cURL 究竟是什么、开发者为何如此依赖它,答案就在于它的简单与灵活。

不过您来这里应该不是为了了解历史(如果您对 cURL 的历史感兴趣,可以阅读这篇文章)。您更想知道的是如何使用它,以及它如何适配您的使用场景。那么,我们先从在您的设备上找到并运行它开始。

如何安装 cURL

如果您使用的是现代系统,cURL 很可能已经预装。在尝试手动安装之前,请先用 curl --version 命令确认是否可用。

在 Windows 上安装 cURL

我们先检查一下系统中是否已经安装了 cURL:

步骤一:打开 CMD

按下“Windows + R”,然后输入“cmd”即可打开命令提示符。

步骤二:检查是否已安装 cURL

粘贴以下 cURL 命令:

curl --version

按下回车键,如果您看到类似这样的版本信息,

IMG1.png

那就说明一切就绪,cURL 已经安装在您的设备上,可以直接跳转到“理解 cURL 语法”部分继续阅读。

步骤三:手动下载 cURL(如有需要)

如果尚未安装,或者想使用更新的版本,请前往 cURL for Windows 下载页面。

IMG2.png

步骤四:选择合适的下载版本

选择适合的构建版本,系统会提示您下载并保存 zip 文件。

IMG3.png

步骤五:为 cURL 新建一个文件夹

建议在一个比较稳妥的位置新建文件夹,例如本地磁盘 C。只需在文件夹列表的任意空白处右键单击,并将鼠标悬停在“新建”上即可。

IMG4.png

步骤六:准备新文件夹

右侧会出现“文件夹”选项,点击它。再点击“新建文件夹”,系统会提示您为其命名,这里我们将其命名为“cURL”。

IMG5.png

步骤七:将 zip 文件保存到新文件夹中

点击“保存”,等待 zip 文件下载完成。

步骤八:找到 cURL 的 zip 文件

找到已下载的文件并选中它。

IMG6.png

步骤九:找到解压 cURL 文件的选项

右键单击下载的 cURL 压缩包,会弹出一个下拉菜单。

IMG7.png

步骤十:解压 zip 文件

选择“全部提取”,并选择要解压到的位置。

IMG8.png

步骤十一:打开解压后的文件

点击“提取”,等待文件解压完成,完成后右键单击新生成的文件。

IMG9.png

步骤十二:复制解压文件的路径

在弹出的下拉菜单中,点击“复制为路径”,然后将路径粘贴到一个安全的地方保存,它看起来应该是这样的:

c:\cURL\curl-8.15.0_4-win32-mingw

步骤十三:打开开始菜单

按下 Windows 键,或点击屏幕左下角的 Windows 图标。在弹出的菜单中输入“环境变量”并打开它。

IMG10.png

步骤十四:打开环境变量

在系统属性菜单底部点击“环境变量”。

IMG11.png

步骤十五:编辑系统路径

在“系统变量”中找到“Path”,选中它,然后点击“编辑”。

IMG12.png

步骤十六:将 cURL 文件夹添加到系统路径中

点击“新建”,粘贴此前复制的解压文件路径。

IMG13.png

步骤十七:保存更改

点击“确定”。

步骤十八:验证安装结果

返回命令行工具,粘贴以下 cURL 命令:

curl --version

一切顺利的话,您现在应该能看到新安装的 cURL 版本号。

在 macOS 上安装 cURL

大多数 macOS 版本都默认自带 cURL,我们先来检查一下这个命令行工具是否已经安装:

步骤一:打开终端

按下“Cmd + Space”,输入“Terminal”打开命令行界面。

步骤二:检查 cURL 是否已经安装

执行以下 cURL 命令:

curl --version

如果显示当前 cURL 的版本信息,就说明一切就绪;如果出现错误,则需要手动安装 cURL。

步骤三:安装 Homebrew(如有需要)

首先需要检查是否已安装 Homebrew:

brew --version

如果出现错误提示,请执行以下命令:

/bin/bash -c "$(curl -fsSL
https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

让安装程序运行,并按照提示完成 Homebrew 的设置和 shell 的更新。

步骤四:重启终端

安装完成后,关闭并重新打开终端。

步骤五:通过 Homebrew 安装 cURL

执行以下命令,通过 Homebrew 安装 cURL:

brew install cURL

步骤六:验证安装结果

执行以下命令确认安装成功:

/opt/homebrew/bin/curl --version

您应该能看到 cURL 版本的详细信息。

在 Linux 上安装 cURL

大多数 Linux 发行版都预装了 cURL,不过我们还是先确认一下。

步骤一:打开终端

按下“Ctrl + Alt + T”打开终端。

步骤二:检查是否已安装 cURL

执行以下 cURL 命令:

curl --version

如果看到版本信息,就说明一切就绪;如果没有,则说明尚未安装 cURL。

步骤三:安装 cURL(如尚未安装)

更新软件包列表:

sudo apt update

然后安装 cURL:

sudo apt install curl -y

到这里,您应该已经知道“cURL 是什么、我的系统中是否已经安装”这个基本问题的答案了。接下来,我们来看看它究竟是如何工作的。

理解 cURL 语法

掌握 cURL 语法最简单的方式就是上手实践。我们将使用 MockAPI 进行练习,这是一款免费工具,可以快速搭建一个测试 API 用于发送请求。

创建 MockAPI 账户以供练习

按照以下步骤创建您的免费 MockAPI 账户:

步骤一:注册 MockAPI

访问官网,创建一个免费账户,并按照提示完成设置。

IMG14.png

步骤二:创建新项目

在 MockAPI 控制台中,点击蓝色的“+”图标创建新项目。

IMG15.png

将其命名为“cURL Test”(或任意您喜欢的名称),API 前缀可以留空。

IMG16.png

点击“创建”,您的项目会出现在下一个界面中。

IMG17.png

步骤三:打开项目

选中项目将其打开。

IMG18.png

步骤四:创建新资源

点击“New Resource”创建新资源,并将其命名为“users”。

IMG19.png

步骤五:在 Schema 中添加自定义字段

您会看到一些默认字段,比如“id”“createdAt”等。点击蓝色的“+”按钮可以添加自己的默认字段,以下是我们用于示例的字段:

Table_Understanding cURL_01.png

在 MockAPI 的 Schema 中,效果如下所示:

IMG20.png

点击“创建”按钮。

IMG21.png

步骤六:打开资源

“users”资源现已就绪。点击 users 方框即可打开数据视图,您可以在此手动添加记录,也可以使用 cURL 自动创建、修改和更新数据。

IMG22.png

您会在地址栏中看到完整的端点 URL,请将其复制并妥善保存。

通过 API 请求掌握 cURL 语法

现在打开终端,让我们开始动手,发送一些 API 请求:

cURL 基本语法

以下是基本的 cURL 命令:

curl [OPTIONS] [URL]

它包含三个核心部分:

  • curl:命令行工具本身
  • [OPTIONS]:用于修改请求的参数标志(稍后会详细介绍)
  • [URL]:您要发送请求的目标地址

了解了这些基础知识后,接下来我们来聊聊使用 cURL 可以发送的不同类型的请求。

使用 cURL 发送 GET 请求

第一种请求类型是 GET,顾名思义,它用于获取数据。

在我们的 MockAPI 设置中,我们将用它发送 API 请求,获取资源中的用户数据。只需在终端中输入 cURL 命令,后面加上此前复制的端点即可:

curl https://68a41d6cc123272fb9b1603e.mockapi.io/users

输出结果如下:

IMG23.png

您会发现什么都没有返回。这是因为我们还没有添加任何实际数据,只是定义了字段。这就引出了第二种 API 请求类型。

发送 POST 请求添加新数据

既然资源目前为空,我们来尝试用 POST 请求添加几个用户。下面是一份模拟数据表:

Table_Understanding cURL_02.png

现在我们需要把这些数据转化为一条 cURL 命令,向 MockAPI 端点发送 POST 请求:

curl -X POST https://68a41d6cc123272fb9b1603e.mockapi.io/users -H "Content-Type: application/json" -d "{\"name\":\"Jane Doe\", \"email\":\"jane@example.com\", \"role\":\"Admin\"}" && ^

curl -X POST https://68a41d6cc123272fb9b1603e.mockapi.io/users -H "Content-Type: application/json" -d "{\"name\":\"John Smith\", \"email\":\"john.smith@example.com\", \"role\":\"Contributor\"}" && ^

curl -X POST https://68a41d6cc123272fb9b1603e.mockapi.io/users -H "Content-Type: application/json" -d "{\"name\":\"Ada Lovelace\", \"email\":\"ada@history.dev\", \"role\":\"Developer\"}"

我们来拆解这条 cURL 命令,让它不再只是一堆看不懂的符号:

  • curl

这是我们用来发送 POST 请求的工具。

  • -X

-X 属于 cURL 命令选项中的一类,叫做标志(flag)。可以把它们想象成一个个小开关,用来改变 cURL 的行为方式:告诉 cURL 要发送哪种类型的请求(比如 POST 而不是 GET)、以何种格式处理数据(比如 JSON)、是否添加请求头,甚至响应结果要保存到哪里。以下是常见 cURL 命令选项的介绍:

Table_Understanding cURL_03.png

我们使用了 -X 这个 cURL 命令选项,紧接着是 POST,这告诉 cURL 您正在发起一个 POST 请求。

  • https://68a41d6cc123272fb9b1603e.mockapi.io/users

这就是您之前从 MockAPI 复制的端点,POST 请求会发送到这里,将新的用户数据添加到 users 资源中。

  • -H "Content-Type: application/json"

这个标志会为您的 POST 请求添加额外信息。在这里,它相当于告诉服务器:“我发送的内容是 JSON 格式。”

  • -d

接下来是 -d 标志,用来告诉 cURL 我们即将在请求体中发送数据。

  • JSON 数据:“{\"name\":\"Jane Doe\", \"email\":\"jane@example.com\", \"role\":\"Admin\"}”

现在,为了理解为什么我们要把整个内容放进引号里并添加这么多反斜杠,不妨先看看这段 JSON 本身简洁易读的原始形式:

{
  "name": "Jane Doe",
  "email": "jane@example.com",
  "role": "Admin"
}

很简单,对吧?但如果直接把它输入终端,就像这样:

curl -X POST -H "Content-Type: application/json" -d {
  "name": "Jane Doe",
  "email": "jane@example.com",
  "role": "Admin"
} https://example.com/users

这样是不行的。无论您使用的是命令提示符、Bash 还是 Zsh,您发送的数据几乎肯定会出错,原因如下:

首先,当 CMD 在 -d 后面看到花括号时,它可能会以为您在开启一个代码块,尤其是在脚本环境下;其次是空格问题——终端不会把这段数据当作一个连续的完整参数,而是会将其拆分成多个独立的片段,比如 {、"name":、"Jane Doe" 等,这些片段都无法正确传递给 cURL。

这就是为什么我们要对双引号进行转义,并把整段数据压缩成一行长字符串——本质上,您是在终端命令里的一个字符串中发送 JSON,而这一点会改变一切。

为了避免这种混乱,我们使用反斜杠来转义内部的引号:

"{\"name\":\"Jane Doe\", \"email\":\"jane@example.com\", \"role\":\"Admin\"}"

这是在告诉 CMD:“内部这些引号并不是字符串的结束标志,它们只是我想发送的 JSON 内容的一部分。”

  • &&

我们来聊聊这两个符号。MockAPI 虽然很适合用来做演示,但一次只能发送一个请求(不支持批量操作)。而我们需要添加三个用户,如果分别用三个独立的 POST 请求来完成,效率实在太低。

这时候 && 就派上用场了。它会告诉终端:“只有在前一条命令执行成功后,才运行下一条命令。”于是,我们把三条 cURL POST 请求串联在同一行中,每一条都要等上一条成功后才会执行。

  • ^(插入符号)

在 Windows CMD 中,每一行通常都会被当作一条独立的命令。如果您在命令还没写完时就按下回车,CMD 就会尝试执行它,问题也就随之而来。

这就是为什么我们要使用插入符号(^)——它会告诉 CMD 当前这一行还没有结束,这样 CMD 就会继续读取下一行的内容。

因此,即使您把命令写成了多行,CMD 仍然会把它当作同一个 POST 请求来处理,插入符号只是让命令更易读,同时不会让终端产生混淆。

接下来,只需对剩下的两个用户重复同样的写法即可。把完整的命令粘贴到终端中,您很可能会看到类似这样的警告:

IMG24.png

不用担心,我们已经用插入符号(^)正确地拆分了各行,直接点击“Paste anyway”即可。

IMG25.png

完成后,cURL 会依次发出每一个 POST 请求,逐一填入各字段。要确认是否成功,回到 MockAPI 资源页面点击“Refresh”即可。

IMG26.png

这里显示的是我们用 cURL 发送这些 POST 请求后,MockAPI 返回的原始 JSON 响应。

每个用户都被包裹在花括号 {} 中,Jane Doe、John Smith 和 Ada Lovelace 这三位用户都被列在同一个长数组里,这说明您的 cURL 命令全部执行成功。

下面快速说明一下每个用户数据中各字段的含义:

  • "createdAt" 是 MockAPI 记录该请求的时间
  • "name"、"email" 和 "role" 就是您发送的原始数据
  • "avatar" 是头像图片的 URL
  • "active" 表示该用户是否被标记为激活状态(我们把它们都设为了 false)
  • "id" 是自动生成的

简而言之,如果您看到的是这样的结果,就说明一切正常:您发送了数据,MockAPI 也成功接收了,这就是 cURL 中 POST 请求的工作方式!

使用 PUT 请求替换数据

当您需要替换资源中已有的数据时,PUT 请求就派上用场了。比如团队新加入了一名开发者,这时就该更新数据库了。

在此之前,我们再来看一眼 users 资源中花括号里的数据:

[
  {
    "createdAt": "2025-08-18T11:45:52.086Z",
    "name": "Jane Doe",
    "avatar": 
"https://cdn.jsdelivr.net/gh/faker-js/assets-person-portrait/female/512/22.jpg",
    "email": "jane@example.com",
    "role": "Admin",
    "active": false,
    "id": "1"
  },
  {
    "createdAt": "2025-08-19T02:33:05.804Z",
    "name": "John Smith",
    "avatar": "https://avatars.githubusercontent.com/u/89730203",
    "email": "john.smith@example.com",
    "role": "Contributor",
    "active": false,
    "id": "2"
  },
  {
    "createdAt": "2025-08-19T00:58:20.811Z",
    "name": "Ada Lovelace",
    "avatar": 
"https://cdn.jsdelivr.net/gh/faker-js/assets-person-portrait/male/512/40.jpg",
    "email": "ada@history.dev",
    "role": "Developer",
    "active": false,
    "id": "3"
  }
]

这样一来就更容易看清我们要处理的数据了——每个用户末尾都有一个 ID:"id": "1"、"id": "2"、"id": "3",这就是我们的参照依据。

如果我们要更新开发者这一职位,就需要定位到 "id": "3" 的用户。

Ada Lovelace 离开了,Ian Deacon 加入进来,我们将使用 PUT 请求完全替换掉 ID 为 3 的用户数据。

下面是我们要发送的更新后的 JSON 数据:

{
  "name": "Ian Deacon",
  "avatar": 
"https://cdn.jsdelivr.net/gh/faker-js/assets-person-portrait/male/512/12.jpg",
  "email": "ian.deacon@example.com",
  "role": "Developer",
  "active": true
}

以下就是实现这一操作的 cURL 命令:

curl -X PUT ^
-H "Content-Type: application/json" ^
-d "{\"name\":\"Ian Deacon\", 
\"avatar\":\"https://cdn.jsdelivr.net/gh/faker-js/assets-person-portrait/male/512/12.jpg\", \"email\":\"ian.deacon@example.com\", 
\"role\":\"Developer\", \"active\":true}" ^
https://68a41d6cc123272fb9b1603e.mockapi.io/users/3

下面逐一说明这段命令的含义:

  • curl

这是我们的命令行工具,无需多作解释。

  • -X PUT ^

-X 参数告诉 cURL 这是一个 PUT 请求,我们用插入符号(^)来换行。

  • -H "Content-Type: application/json" ^

-H 参数用于添加请求头,这里是告诉 cURL 我们发送的是 JSON 数据,再次使用插入符号来保持命令整洁。

  • -d "{\"name\":\"Ian Deacon\", \"avatar\":\"https://cdn.jsdelivr.net/gh/faker-js/assets-person-portrait/male/512/12.jpg\", \"email\":\"ian.deacon@example.com\", \"role\":\"Developer\", \"active\":true}" ^

-d 参数的意思是:“cURL,请求体里有数据。”实际的 JSON 内容用引号包裹,并通过反斜杠转义,以免 CMD 误读;随后我们再用插入符号换行。

  • https://68a41d6cc123272fb9b1603e.mockapi.io/users/3

最后,我们把整条命令指向目标 API 端点。注意到区别了吗?这次端点末尾多了 /3,正是我们要更新的那个用户的 ID。

把这段代码粘贴到终端中并执行,如果出现警告,直接点击“Paste anyway”即可。

IMG27.png

就这样,我们把 Ada Lovelace 替换成了 Ian Deacon。

这是我们在 CMD 中使用 PUT 请求执行的完整 cURL 命令。我们将目标指向 /users/3(也就是 Ada 原来的 ID),并把她的数据替换成了 Ian 的:新姓名、新邮箱、新头像,还把他标记为了激活状态。

返回结果确认了替换成功,回到资源页面点击“Refresh”也可以验证这一点。

IMG28.png

现在可以看到,Ian Deacon 已经作为 ID 为 3 的开发者出现在这里了。

使用 PATCH 请求更新字段

Jane Doe 刚刚获得晋升,现在是 CEO,我们需要在 API 中反映这一变化。

这正是 PATCH 请求派上用场的地方——当您只想更新某一项数据而不改动其余内容时,它再合适不过。

在这个例子中,我们已经知道 Jane 的 ID 是 1,所以直接定位到这个 ID;由于只需要修改她的角色,我们在数据中也只传入这一个字段即可。

以下是对应的 JSON 数据:

{
  "role": "CEO"
}

以下是对应的 cURL 命令:

curl -X PATCH ^
-H "Content-Type: application/json" ^
-d "{\"role\":\"CEO\"}" ^
https://68a41d6cc123272fb9b1603e.mockapi.io/users/1

已经开始熟悉这种写法了吧?我们来逐一拆解一下:

  • curl X PATCH ^

这里我们通过 -X 参数告诉 cURL 这是一个 PATCH 请求,然后用插入符号结束这一行。

  • -H "Content-Type: application/json" ^

-H 参数依旧用于把请求头设置为 JSON,和之前的做法一样,再次用插入符号换行。

  • -d "{\"role\":\"CEO\"}" ^

这里我们用 -d 参数传入数据,只更新 role 这一个字段,并为它赋一个新值。

  • https://68a41d6cc123272fb9b1603e.mockapi.io/users/1

最后,我们直接访问该 API 端点,目标是 ID 为 1 的用户。

把这条 cURL 命令粘贴进去并按下回车(和之前一样,忽略报错即可)。

IMG29.png

可以清楚地看到,cURL 已成功将角色从 Admin 更新为 CEO,这一变化在资源中也同步体现出来:

IMG30.png

使用 DELETE 请求删除记录

假设公司刚被收购,我们的贡献者 John 被辞退了,cURL 可以轻松地在 API 中反映这一变化,只需执行:

curl.exe -X DELETE ^
https://68a41d6cc123272fb9b1603e.mockapi.io/users/2

流程和之前一样:先写 cURL,再用 -X 参数声明请求类型(这里是 DELETE),然后定位到 John 的专属端点 /users/2。

粘贴这条 cURL 命令,忽略报错,然后按下“Enter”。

IMG31.png

回到您的 API 页面并刷新:

IMG32.png

John 已经不在了,ID 2 已成功从 API 中删除。

如果您想删除另一条记录,比如 ID 为 1 的记录,只需修改端点末尾的数字即可:

https://68a41d6cc123272fb9b1603e.mockapi.io/users/1

就是这么简单!

为什么 cURL 命令如此强大?

说完这些,我们再来聊聊为什么 cURL 会成为各类终端工作流中高度依赖的工具之一。

协议无关性

设想这样一个场景:您需要备份公司的关键资源,部分日志来自云服务器,可以通过 HTTPS 访问;日常报告则存放在老旧的本地服务器上,只能通过 FTP 访问。

此外,还有一些机密知识产权(IP)数据,只能从一台加固的堡垒机(bastion)通过安全复制协议(SCP)访问;要管理这一切,通常意味着要在多种工具之间切换,或者为每种协议单独编写客户端。

但使用 cURL 就不必如此,这正是其协议无关性的优势所在:您可以用同样的 cURL 命令格式访问上述所有数据源。

以下是一条使用 -i 参数、针对 GitHub 公共 API 发出的基本 GET 请求 cURL 命令:

curl -i https://api.github.com

要理解其底层原理,需要先了解libcurl——这个可移植的 C 语言库支撑着您执行的每一条 cURL 命令,在幕后处理协议、连接、数据传输、重试和错误等全部网络逻辑。

执行命令后,cURL 首先要做的是解析 URL 协议头。https:// 这个前缀之所以重要,是因为它告诉 cURL 应该从 libcurl 中调用哪个协议处理程序;在这里,它会询问:“我们有没有针对 HTTPS 的处理程序?”libcurl 给出肯定的答复。

所谓处理程序,是 libcurl 内部一个独立的协议模块,知道如何与特定协议进行通信。以 HTTPS 为例,它知道如何建立安全连接、发送请求、格式化请求头或命令、接收并解析响应——上面那条响应正是这样得到的。

现在,假设您想查询GNU Bash release目录,尽管这个目录是通过 FTP 托管的,您依然可以使用同样熟悉的语法:

curl -i ftp://ftp.gnu.org/gnu/bash/

这就是协议无关性的核心所在:您只需替换 URL,剩下的交给 cURL 处理即可。以下是它支持的主要协议:

  • HTTP:互联网的基础协议,支撑 REST API、网站等
  • HTTPS:加密连接的安全版 HTTP
  • FTP:用于远程目录和旧系统的文件传输协议
  • FTPS:基于 SSL/TLS 的安全文件传输版 FTP
  • SFTP:基于 SSH 的文件传输协议,常用于安全性要求较高的企业环境
  • SCP:安全复制协议,同样基于 SSH
  • SMTP:用于发送邮件
  • SMTPS:安全版 SMTP
  • POP3:用于接收邮件
  • POP3S:安全版 POP3
  • IMAP:另一种邮件协议
  • IMAPS:安全版 IMAP
  • LDAP:用于访问目录服务
  • LDAPS:安全版 LDAP
  • DICT:词典协议(用于查询释义)
  • FILE:通过 file:// URI 访问本地文件
  • TELNET:用于操作 telnet 服务
  • TFTP:简单文件传输协议(常用于嵌入式系统)
  • RTMP:用于流媒体传输的实时消息传输协议
  • RTSP:用于媒体传输的实时流传输协议
  • GOPHER:早于 HTTP 的内容协议,出于兼容旧系统的原因仍受支持
  • SMB / SMB2:Windows 网络文件共享协议

不受平台限制

cURL 强大的另一个原因在于它不受平台限制——这不仅意味着它可以在任何平台上运行,更意味着无需任何修改即可在任意平台上运行。

无论在 Linux、macOS、Windows 还是其他系统上,之前用于从 GitHub 或 GNU Bash 目录获取信息的同一条命令都会返回相同的结果。

这一切都要归功于 cURL 背后的核心——libcurl。正如之前提到的,它是一种基于 C 语言、轻量且高度可移植(重点是可移植)的网络引擎。

只要存在 C 编译器,libcurl 就能运行,这意味着同一条 cURL 命令既能在运行 Debian 的 2013 款 ThinkPad 上执行,也能在 ARM 服务器的 Docker 容器中运行,还能在使用 PowerShell 的 Windows 11 设备上运行。

不限定使用场景

cURL 不关心您的身份角色,它并非只为数据分析师或网络爬虫开发者而生,它唯一在意的是您是否懂得互联网的“语言”。

可以把 cURL 想象成在网络中运送数据的车厢,而 libcurl 则是驱动这些车厢在任意轨道(协议)上运行的引擎。

这正是 cURL 能够适配多种角色的原因:

  • 开发者

进行网络开发时,您需要可靠、可测试的请求,cURL 可以成为代码与外部世界之间的默认桥梁。无论请求头、负载还是协议如何设置,cURL 都能顺畅执行。

  • 安全工程

借助简单且可脚本化的命令,cURL 可以帮助您测试服务器漏洞、验证 TLS 配置、评估防火墙或 WAF 规则的响应情况,清晰呈现系统的实际行为。

  • 数据专业人员

如果您的工作涉及从网站收集数据,cURL 可以帮助实现自动化流程。不过,对于动态或大量依赖 JavaScript 的网站,由于 cURL 在处理客户端渲染方面存在局限,通常更适合搭配其他工具使用。

  • 金融与科研

金融从业者常用 cURL 轮询 Benzinga、Reuters、Finviz 等财经新闻 API,从而自动掌握市场动态,无需人工查看。在科研领域,cURL 可用于从 PubMed 等来源获取科学数据,或向远程计算服务提交任务。

如果您所在的行业依赖数据,而这些数据可以通过 URL 访问,那么 cURL 可以成为得力工具。但客观来说,它并非万能:面对大量依赖 JavaScript 的页面时表现吃力,也无法单独绕过高级反机器人防护机制。

cURL 的局限之处

假设您想抓取Amazon 上好评较多的手机壳数据,听起来很简单,对吧?

您执行以下 cURL 命令:

curl -i 
https://www.amazon.com/Best-Sellers-Cell-Phones/zgbs/wireless/7072561011

返回结果如下:

IMG33.png

您会看到 503 状态码,这说明服务器在线,但拒绝放行。原因在于 cURL 无法识别 JavaScript,既无法处理动态渲染,也无法绕过 Amazon 多层反机器人防护机制。它只能获取服务器返回的原始响应,而 Amazon 在这里并未提供任何有用内容。

简而言之,当内容公开可访问、或易于直接获取时,cURL 往往能顺利完成任务;一旦内容被 JavaScript、防火墙或速率限制层层阻拦,就需要借助更强大的工具。

第一步可以打开浏览器的网络面板,查看数据是否通过简洁的 API 或 JSON 文件加载。如果是,那么 cURL 仍然可能适用。

如果不是,就需要借助 Selenium 等无头浏览器,它们能够模拟真实用户会话,并像浏览器一样渲染页面。在此基础上,可以结合更智能的抓取策略,例如退避逻辑、住宅代理轮换,以及更接近真实用户行为的操作模式。

这种组合能帮助您借助稳定的 IP 发送更接近真实用户行为的请求,不易引发网站警觉。

用 cURL 抓取 Amazon 数据,不再被 503 拦截

获取住宅代理

排查常见 cURL 错误

至此,您已经了解了 cURL 是什么、如何安装、以及其工作原理。但实际使用中难免会遇到问题,因此了解常见的 cURL 错误及其排查方法同样重要。

连接错误

有时执行 cURL 命令后,会出现以下错误:

curl: (7) Failed to connect to example.com port 443: Connection refused

cURL 成功访问了服务器,但连接被拒绝,可能的原因如下:

  • 端口错误:请求的是 443 端口上的 HTTPS,但服务器只在 80 端口提供普通 HTTP 服务
  • 防火墙拦截:服务器可能通过防火墙屏蔽了您的 IP、所在地区或整个端口
  • 服务未运行:nginx 或 Apache 可能未启动,或配置有误而未监听请求
  • DNS 不匹配:域名可以解析,但服务器无法识别该域名,或未配置为处理相应请求

总之,服务器确实存在,只是没有放行 cURL。您需要找出究竟是哪一把“锁”挡住了您的“钥匙”,具体排查方法取决于目标网站的情况。

Ping 目标地址

首先可以 ping 该网站,检查其在网络层面是否可达。如果 ping 通但 cURL 请求失败,说明服务器在线,问题很可能出在端口或服务本身。

ping yourtarget.com

使用 netcat(或 telnet)测试端口连通性

确认服务器可通过 ping 访问后,下一步是检查目标端口是否确实处于监听状态。

这时就需要用到 nc,执行以下命令:

nc -zv yourtarget.com 443

具体说明如下:

  • nc 是 netcat 的缩写
  • -z 表示仅探测端口而不发送数据
  • -v 表示启用详细模式,以获取清晰的反馈信息
  • 443 是端口号,HTTPS 的标准端口

如果端口开放并接受连接,会显示成功信息;如果不行,则会明确告知失败原因。由此即可判断服务是否在线,或 cURL 是否遇到了死路。

如果未安装 netcat,也可以使用 telnet,执行以下命令:

telnet example.com 443

切换到详细模式,查看 cURL 所看到的信息

当情况不如预期时,可以开启详细模式,追踪连接的每个步骤,从而准确定位问题所在。

使用以下 cURL 命令执行:

curl -v https://yourtarget.com

您将看到完整的执行过程。

使用 traceroute 查看数据包在何处中断

如果您身处防火墙或代理之后,traceroute 可以帮助您追踪请求在到达服务器之前经过的每一个节点(无论是否成功到达),从而清楚看到连接在何处中断。

执行方法如下:

traceroute yourtarget.com

这样即可清晰看到完整的路由路径。

SSL 证书错误

SSL 全称为 Secure Sockets Layer(安全套接层),TLS 全称为 Transport Layer Security(传输层安全协议),二者都是保障网络连接安全的协议。

您每天都在使用它们,却很少留意——输入 https:// 时地址栏出现的小锁图标,正是 SSL 在发挥作用。

SSL 证书就像服务器的数字护照,用于确认服务器身份、证明连接已加密,并表明该证书由受信任的机构签发。

一张典型的 SSL 证书通常包含以下信息:

  • 服务器的公钥
  • 证书适用的域名(如 api.example.com)
  • 签发该证书的证书颁发机构(CA)
  • 有效期
  • CA 的数字签名

当证书存在问题时就会出现错误,常见原因如下:

  • 自签名证书:服务器自行签发证书,而非使用受信任的机构
  • 证书过期:证书的有效期已结束,不再被视为安全
  • 域名不匹配:您访问的是 abc.com,但证书上显示的是 xyz.com
  • 根证书不受信任:签发该证书的机构不在您的受信任证书列表中
  • 系统时间误差:系统时钟不准确,可能导致有效证书显示为已过期或尚未生效

如果您访问的网站并非由您管理,首先应联系网站所有者核实情况。您也可以在浏览器中打开该网站,点击锁图标查看证书详情,通常即可判断证书是否已过期、是否为自签名、或是否由系统不信任的 CA 签发。

如果问题出在证书颁发机构不受信任,不要直接跳过验证,可以通过以下 cURL 命令手动指定受信任的 CA:

curl --cacert /path/to/trusted-root.pem https://yourtarget.com

这样既能保证安全性,又无需关闭 SSL 验证。如果您本身管理该服务器,更推荐直接更新证书。只有在确实必要时,才应跳过证书验证。

超时与响应缓慢

根据您的 IP、目标网站以及尝试获取的数据类型,cURL 请求有时会像卡住一样迟迟没有响应,但这并不一定意味着服务器已宕机。如果这种情况经常出现,不妨了解如何设置 cURL 超时时间,让请求快速失败,而不是无限期挂起。

服务器可能处于不可用、过载、或故意拖延响应的状态。有些目标网站看似即将返回响应,实则卡住不动,这可能是有意为之,也可能是配置错误所致。以下是解决该问题的方法。

Ping 目标地址

首先 ping 目标地址:

ping yourtarget.com

如果没有响应,问题可能出在网络层面:服务器可能已宕机、DNS 配置有误,或防火墙正在拦截请求。

接下来需要逐步排查缩小范围。

检查端口是否开放

接下来,确认目标端口是否确实处于监听状态,这时可以借助 netcat 或 telnet。

Netcat:

nc -zv yourtarget.com 443

nc 是 netcat 的缩写,-z 表示仅扫描端口而不发送数据,-v 则启用详细输出,便于查看具体情况。

如果没有安装 netcat,可以尝试 telnet,它的普及度更高,命令也更简单:

Telnet:

telnet yourtarget.com 443

使用详细模式追踪连接的各个阶段

如果仍然无法判断问题所在,可以切换到详细模式,它会展示连接的每个阶段,帮助您准确定位卡顿位置。

curl -v https://yourtarget.com

当您需要查看 cURL 所看到的信息时,可以使用该模式。

使用 curl -w 测量各阶段耗时

这种方法设置起来稍显繁琐,但配置完成后使用非常简单,它可以测量连接各阶段所耗费的时间,从而准确找出延迟出现的位置。

  • 第一步:打开文本编辑器

打开一个空白文本编辑器,用于创建自定义输出格式。

  • 第二步:粘贴计时模板

添加 cURL 计时变量,用于追踪请求的各个阶段。

DNS Lookup:  %{time_namelookup}s
Connect:     %{time_connect}s
SSL Handshake: %{time_appconnect}s
Start Transfer: %{time_starttransfer}s
Total:       %{time_total}s

您刚才做的是设置自定义输出格式,让 cURL 清楚显示延迟具体出现在哪个环节。每一行都对应请求过程中的一个阶段:

  • DNS 查询:将域名解析为 IP 所花费的时间
  • 连接:建立到该 IP 的连接所花费的时间
  • SSL 握手:协商安全连接所花费的时间
  • 开始传输:服务器实际开始发送数据的时间点
  • 总耗时:整个请求从开始到结束所花费的时间
  • 第三步:保存文件并复制其路径

将文件保存为 curl-format.txt(在“保存类型”框中选择“所有文件”,以避免生成 .txt.txt 后缀)。复制该文件的路径。

  • 第四步:执行计时命令

使用 -w 参数运行 cURL 并结合格式文件,即可查看各阶段的耗时详情。以下是对应的 cURL 命令:

curl -w "yourfilepath" -o NUL -s https://yourtarget.com

您将清楚看到请求在前面提到的每个阶段分别花费了多少秒。

cURL 与 wget:该选哪个工具?

很多人在了解 cURL 是什么之后,也会好奇它与 wget 相比有什么不同。

乍一看,两者十分相似:都能从 URL 获取数据,都在终端中运行,也都常被用在脚本里,很容易混淆。但它们其实并不相同。

那么两者究竟有什么区别?又有哪些重合之处?该在什么情况下选择其中一个?

了解 cURL 与 wget 的工作原理

一边是 cURL,前面已经详细介绍过。另一边是 wget,同样非常实用。

wget 的名字已经说明了一切:web get,意思就是从网络获取文件。给它一个 URL,它就会把文件抓取下来,没有多余的花样,只负责获取和保存。需要的话,它还能递归下载。

下面是一条基础命令,展示它的用法:

wget https://wordpress.org/latest.zip

这条命令会将最新版 WordPress 的压缩包下载到当前目录,是不是很简单?

接下来把 cURL 和 wget 放在一起对比一下:

  • 两者都支持 HTTP、HTTPS 和 FTP
  • 两者都可以配合代理使用
  • 两者都能用来从 URL 下载文件
  • 两者都提供身份验证方式
  • 两者都能跟随重定向(cURL 使用 -L,wget 使用 --max-redirect)
  • 两者在 Shell 脚本和定时任务(cron job)中都表现出色

cURL 与 wget 的区别

两者的区别主要体现在默认行为上。

交互性与自定义能力

这两种工具最明显的区别在于,它们对传输过程的控制程度不同。

  • 自定义 HTTP 方法

使用 cURL,您可以完全掌控请求方式:PUT、DELETE、PATCH,任务需要什么就用什么,前面已经介绍过。而 wget 基本只能用 GET 和 POST,仅此而已。

  • 自定义请求头

如果您在对接 API,几乎总会用到请求头。cURL 可以轻松设置认证令牌、User-Agent、内容类型等各种所需内容。wget 虽然能伪造 User-Agent,但也就到此为止了。

  • 表单提交

cURL 可以使用 POST 模拟浏览器式的表单提交。wget 也能发送数据,但方式比较生硬,因为它本来就不是为这种精细操作设计的。

  • Cookie 处理

两种工具都支持 Cookie。cURL 需要您用 -b 和 -c 手动控制,而 wget 更简单,只需设置一次,它就会自动保存并发送 Cookie。

  • FTP 上传

需要通过 FTP 或 SFTP 上传文件?cURL 可以干净利落地完成。wget 不支持上传,只能下载。

文件下载与续传

这方面 wget 表现出色,只需加上 -c 参数。如果下载中途中断,它会检查本地文件,与服务器上的版本进行比对,并从中断的地方精确续传。以下是对应的 wget 命令:

wget -c https://example.com/yourfile.zip

cURL 也能续传,但前提是本地已有部分文件、服务器支持范围请求,并且语法正确(-C - 这个参数很关键)。如果涉及重定向或 Cookie,情况就会变得不太稳定。

简单来说,wget 天生就是为应对各种复杂情况而设计的;cURL 只有在精心配置的情况下才能做到同样的事。以下是用 cURL 续传文件下载的命令:

curl -C - -O https://example.com/yourfile.zip

如果您想下载整个网站,wget是更合适的选择,它可以完整镜像整个网站,包括 HTML、图片、脚本、结构等所有内容。

只需在命令中加上 --mirror 即可开始工作。cURL 并不是为此设计的,它一次只能下载一个文件,仅此而已。

安全性与身份验证

在对接现代 API、使用加密连接或需要安全传递凭证时,cURL 是更合适的选择,它可以让您:

  • 附加客户端证书以实现双向 TLS 验证
  • 指定自定义 CA 证书包
  • 在有严格合规要求时锁定加密套件
  • 强制指定 SSL/TLS 版本,这在对接旧版 API 或安全限制严格的金融系统时尤为重要

wget 虽然支持 HTTPS 并能验证证书,但功能也就到此为止了。

该在什么情况下使用哪种工具?

Table_Understanding cURL_04.png

结语

能看到这里,非常不错!您现在已经了解了 cURL 是什么、它的工作原理、擅长做什么,以及适合在什么场景下使用。您也见过它的语法、参数,以及各种边界情况。

也许您已经在考虑如何把它融入自己的工作流程,又或者您发现自己的使用场景需要更强大的工具,比如 Selenium 或代理轮换引擎。

但如果您只是需要一种简单可靠的工具来通过 HTTP 下载文件,wget 可能是更简便、更稳定的选择。不管选哪种,现在您已经有了足够的选项,放心使用 cURL 吧。

想结合代理等功能进一步提升 cURL 的使用效果?欢迎加入我们的 Discord 社区。

什么是 cURL 命令?

cURL 命令可以直接在终端中向 URL 传输数据或从 URL 获取数据。您可以用它发送 HTTP 请求、下载文件、测试 API、发送数据或调试网络流量,可以把它理解为一种能与互联网交互的命令行工具。

cURL 代表什么?

cURL 是 Client URL 的缩写。之所以这样命名,是因为它能让您的设备(客户端)通过多种协议与 URL 进行交互,因此得名 Client URL。

cURL 是默认安装的吗?

如果您使用的是 Linux 或 macOS,cURL 通常是预装的,可以打开终端运行 curl --version 来检查。在 Windows 上,从 Windows 10 版本 1803 开始默认也会包含 cURL。如果发现它缺失或运行异常,也可以按照前文介绍的方法安装或更新。

cURL 有什么用途?

cURL 用于通过 HTTP、FTP 等支持的协议向服务器传输数据或从服务器获取数据,常用于测试 API、下载文件,以及在终端中与 URL 进行交互。

了解更多
-

相关文章