curl 指令:選項用法、POST 請求與檔案下載

測試環境RHEL 系列AlmaLinux 9.8root 帳號2026-10-28 確認

curl 指令是在終端機向網址送出請求,並把回應原樣輸出的工具。只要一行指令,就能確認頁面內文、標頭與狀態碼。我們從 AlmaLinux 9 伺服器向 WordPress 網站送出 curl 請求,結果 http 網址以 301 回應指向 https 網址,未經驗證的 REST API 請求則以 401 遭到拒絕。

1️⃣ curl 指令基本用法與回應內文

在 curl 後面接一個網址,就會向該網址送出 GET 請求,並把回應內文輸出到畫面上。請求 WordPress 產生的 robots.txt 時,三行的檔案內容原樣顯示出來。

curl https://example.com/robots.txt
User-agent: *
Disallow: /wp-admin/
Allow: /wp-admin/admin-ajax.php

很容易以為會看到和在瀏覽器輸入網址時相同的畫面,但 curl 輸出的是伺服器送來的原始 HTML。curl 不會執行指令碼,也不會另外請求圖片和 CSS。頁面 HTML 很長,所以網頁網址的輸出會用管線交給 head,只確認前幾行。

curl -s https://example.com/ | head -n 2
<!DOCTYPE html>
<html lang="ko-KR">

加上 -s 後,用管線傳遞輸出時混在畫面上的進度顯示會被隱藏。只用首頁網址收到的 HTML 為 96,679 位元組。圖片和指令碼檔案不包含在這個大小內。

2️⃣ 用 curl -I 確認標頭、用 -L 跟隨重新導向

只看內文無法得知請求是否成功,因此狀態碼和標頭要另外用 -I 確認。-I 會送出 HEAD 請求,不含內文、只輸出回應標頭。就像不拆開包裹,只看貨運單一樣。

curl -I https://example.com/
HTTP/2 200
server: nginx/1.28.0
date: Wed, 28 Oct 2026 05:29:23 GMT
content-type: text/html; charset=UTF-8
vary: Accept-Encoding
last-modified: Tue, 27 Oct 2026 21:12:18 GMT
cache-control: max-age=0
expires: Wed, 28 Oct 2026 05:29:23 GMT
accept-ranges: none
alt-svc: h3=":443"; ma=86400

第一行的 [HTTP/2 200] 就是狀態碼。下方接著是伺服器類型、內容類型和快取相關標頭。把同樣的請求送到 http 網址,會得到 301,並在 [Location] 標頭中顯示要前往的 https 網址。

curl -I http://example.com/
HTTP/1.1 301 Moved Permanently
Server: nginx/1.28.0
Date: Wed, 28 Oct 2026 05:27:51 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://example.com/

不加選項請求 http 網址時,curl 沒有再向 [Location] 的網址送出請求,只輸出 301 回應的 7 行內文就結束了。

curl http://example.com/
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.28.0</center>
</body>
</html>

加上 -L 後,curl 會再向 [Location] 的網址送出請求。和 -I 合併成 -IL 執行時,301 回應標頭之後會依序出現 200 回應標頭。

curl -IL http://example.com/
HTTP/1.1 301 Moved Permanently
Server: nginx/1.28.0
Date: Wed, 28 Oct 2026 05:29:23 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://example.com/

HTTP/2 200
server: nginx/1.28.0
date: Wed, 28 Oct 2026 05:29:23 GMT
content-type: text/html; charset=UTF-8
vary: Accept-Encoding
last-modified: Tue, 27 Oct 2026 21:12:18 GMT
cache-control: max-age=0
expires: Wed, 28 Oct 2026 05:29:23 GMT
accept-ranges: none
alt-svc: h3=":443"; ma=86400

依選項不同,請求會送出幾次、畫面上會出現什麼,可以在下方圖表中依序比較。

🧭 依 curl 選項區分的請求與輸出:http 網址的 301
說明圖解
⚙️ 選項
$ curl -I -L -IL http://example.com/
① GETHEAD 要求http://example.com/
➜
301 Moved PermanentlyLocation: https://example.com/
② GETHEAD 要求https://example.com/不請求
➜
200無回應
🖥️ 畫面上輸出的內容
301 回應內文(HTML 7 行)
301 回應標頭 7 行
200 回應內文(首頁 HTML 96,679 位元組)
301 回應標頭 7 行 → 200 回應標頭 10 行
不加選項請求時,curl 不會再向 [Location] 的 https 網址送出請求,只輸出 301 回應的內文。
-I 以 HEAD 請求只接收標頭,不向要前往的網址再次請求,輸出 301 狀態與 [Location] 標頭。
-L 會向 [Location] 的 https 網址再請求一次,輸出最後 200 回應的內文。
-IL 會依序輸出兩次請求的回應標頭。301 之後接著 200。

3️⃣ 用 curl 指令下載檔案(-o、-O)

-O 會沿用網址最後的檔案名稱,儲存到目前的資料夾。儲存期間畫面上顯示的是進度,而不是內文。

curl -O https://example.com/wp-includes/images/w-logo-blue.png
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100  3113  100  3113    0     0   178k      0 --:--:-- --:--:-- --:--:--  190k
ls -l w-logo-blue.png
-rw-r--r-- 1 root root 3113 Oct 28 14:29 w-logo-blue.png

下載完成後,進度顯示的 [Total] 與 [Received] 都是 3113,用 ls -l 確認的檔案大小也同樣是 3,113 位元組。

若要自己決定儲存的名稱,就在 -o 後面寫上檔案名稱。下方是把首頁網址存成 home.html 的結果。

curl -o home.html https://example.com/
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100 96679    0 96679    0     0  4291k      0 --:--:-- --:--:-- --:--:-- 4291k
ls -l home.html
-rw-r--r-- 1 root root 96679 Oct 28 14:29 home.html

-O 會直接使用網址結尾的檔案名稱,因此不適合以斜線結尾的頁面網址。對首頁網址加上 -O,會因找不到檔案名稱而以下方錯誤結束。

curl -O https://example.com/
curl: Remote file name has no length!
curl: (23) Failed writing received data to disk/application

4️⃣ curl POST 請求與 JSON 資料傳送

要讓原本只讀取的請求附帶資料送出時,使用 -d;要說明資料格式時,再加上 -H。-d 會把後面寫的資料當作 POST 內文送出。沒有另外指定時,[Content-Type] 為 [application/x-www-form-urlencoded]。

使用 -d 後,請求方式會變成 POST,所以 [-X POST] 可以省略。官方文件也說明通常不需要 -X。

傳送 JSON 時,用 -H 把 [Content-Type] 改成 [application/json]。下方是不經驗證向 WordPress REST API 送出建立文章請求的結果。

curl -s -X POST -H 'Content-Type: application/json' -d '{"title":"curl test"}' https://example.com/wp-json/wp/v2/posts
{"code":"rest_authentication_error","message":"\uc8c4\uc1a1\ud569\ub2c8\ub2e4. REST API \uc694\uccad\uc744 \ud560 \uc218 \uc788\ub294 \uad8c\ud55c\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.","data":{"status":401}}

請求的網站 封鎖了未登入的 REST API 請求 因此 code 傳回 [rest_authentication_error],狀態為 401。由於同樣的設定,以 GET 向同一網址請求文章列表也會傳回 401。message 的值是以網站語言寫成的錯誤訊息,轉成 JSON 的 Unicode 表示法後的樣子。

只想確認狀態碼時,用 [-o /dev/null] 丟棄內文,再用 -w 只輸出 http_code。

curl -s -o /dev/null -w '%{http_code}\n' -X POST -H 'Content-Type: application/json' -d '{"title":"curl test"}' https://example.com/wp-json/wp/v2/posts
401

5️⃣ 用 curl 指令測量回應時間(-w)

回應很慢時,很容易只看 total,但要知道時間是花在連線還是伺服器處理,必須把各階段的時間分開輸出才能確認。-w 會在請求結束後,以指定的格式輸出測量值。值會填入格式中 [%{變數名稱}] 的位置。

用 [-o /dev/null] 丟棄內文,用 -s 隱藏進度顯示。

curl -o /dev/null -s -w 'code: %{http_code}\nconnect: %{time_connect}\ntls: %{time_appconnect}\nttfb: %{time_starttransfer}\ntotal: %{time_total}\n' https://example.com/
code: 200
connect: 0.001507
tls: 0.017728
ttfb: 0.021912
total: 0.022825

connect 是 TCP 連線,tls 是 TLS 交握, ttfb是直到第一個位元組即將傳送之前,total 是直到傳輸結束的時間。四個值都是從請求開始時累計的秒數。

執行 curl 的伺服器和接收請求的網站在同一台伺服器上,所以連線只花 0.0015 秒,到 TLS 交握完成為 0.0177 秒,到第一個位元組為 0.0219 秒。從 TLS 交握結束到第一個位元組抵達約 0.004 秒。官方文件說明這個區間包含伺服器產生結果的時間。

同一個指令再執行三次時,total 介於 0.0219 秒到 0.0226 秒之間。

🔲 curl 指令模擬器

在下方模擬器中,可以親自輸入到目前為止的指令,確認各選項的輸出有什麼不同。

curl 指令模擬器curl 7.76.1
[root@server work]#
用鍵盤 ↑↓ 鍵可叫出先前輸入過的指令。

🔢 FAQ & 推薦內容

-s 會同時隱藏進度顯示和錯誤訊息。請求不存在的網址時,什麼都沒有輸出,只留下結束代碼 6。若同時指定 -sS,進度顯示會隱藏,但 [curl: (6) Could not resolve host] 這類錯誤仍會照常顯示。

使用 -k 會略過確認連線是否安全的步驟,因此 curl 不會確認連上的伺服器是否真的屬於該網域就傳送資料。curl 會確認伺服器憑證中是否包含所連線的網域名稱,以及能否透過憑證存放區驗證。出現這個錯誤時,請先確認憑證的網域名稱與發行機構。

依官方文件,收到 301、302、303 回應時,curl 會把下一個請求改為 GET 傳送。要維持 POST,請使用 [--post301] 這類專用選項。用 -X 指定的方法優先於這個轉換。

🧭 網路指令推薦內容 9 篇 · 2 份參考資料
🗂️ 網路指令
📄 SSH 指令 📄 rsync 指令 📄 wget 指令 📄 rz · sz 指令 📄 curl 指令
📄 host 指令 📄 nslookup 指令
📄 ip 指令 📄 netstat · ifconfig 指令

ℹ️ 聯盟行銷說明
本站內容包含聯盟行銷連結。訪客透過這些連結購買商品或服務時,本站會從賣家獲得佣金。在這個過程中,購買者支付的金額(遇到活動折扣時金額會降低↓)並不會因此提高。刊登的價格、折扣與庫存資訊以撰寫當時為準,可能與實際情況不同,購買前請向賣家做最後確認。商品的挑選與評價依本站自訂的標準撰寫,是否支付佣金不會影響介紹順序或評價內容。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

Prove your humanity: 5   +   4   =