Lệnh curl: cách dùng tùy chọn, yêu cầu POST và tải tệp

Môi trường thử nghiệmHọ RHELAlmaLinux 9.8Tài khoản rootKiểm tra ngày 2026-10-28

Lệnh curl là công cụ gửi yêu cầu tới một địa chỉ web từ terminal và in phản hồi ra đúng như nhận được. Chỉ với một dòng lệnh, bạn có thể kiểm tra nội dung trang, header và mã trạng thái. Khi chúng tôi gửi yêu cầu curl từ máy chủ AlmaLinux 9 tới một trang WordPress, địa chỉ http trả về phản hồi 301 chỉ sang địa chỉ https, còn yêu cầu REST API không xác thực bị từ chối với 401.

1️⃣ Cách dùng cơ bản lệnh curl và nội dung phản hồi

Đặt một địa chỉ sau curl thì curl gửi yêu cầu GET tới địa chỉ đó và in nội dung phản hồi ra màn hình. Khi chúng tôi yêu cầu tệp robots.txt do WordPress tạo, nội dung tệp ba dòng hiện ra đúng như vậy.

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

Bạn dễ mong thấy trang giống như khi gõ địa chỉ vào trình duyệt, nhưng thứ curl in ra là HTML thô mà máy chủ gửi. curl không chạy script và không yêu cầu riêng hình ảnh hay CSS. HTML của trang dài, nên với địa chỉ trang web, chúng tôi chuyển đầu ra qua pipe sang head và chỉ xem vài dòng đầu.

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

Thêm -s sẽ ẩn thanh tiến trình vốn lẫn vào màn hình khi chuyển đầu ra qua pipe. HTML nhận được chỉ từ địa chỉ trang chủ là 96.679 byte. Kích thước này không gồm tệp hình ảnh và script.

2️⃣ Kiểm tra header bằng curl -I và theo chuyển hướng bằng -L

Chỉ nhìn nội dung thì không biết yêu cầu có thành công hay không, nên bạn kiểm tra riêng mã trạng thái và header bằng -I. -I gửi yêu cầu HEAD và chỉ in header của phản hồi, không có nội dung. Giống như xem phiếu gửi hàng mà không mở hộp.

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] ở dòng đầu là mã trạng thái. Bên dưới là loại máy chủ, loại nội dung và các header liên quan đến bộ nhớ đệm. Nếu gửi cùng yêu cầu tới địa chỉ http, bạn nhận 301 kèm địa chỉ https cần chuyển tới trong header [Location].

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/

Khi yêu cầu địa chỉ http không kèm tùy chọn, curl không gửi lại yêu cầu tới địa chỉ trong [Location] mà chỉ in 7 dòng nội dung của phản hồi 301 rồi kết thúc.

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>

Thêm -L thì curl gửi lại yêu cầu tới địa chỉ trong [Location]. Kết hợp với -I thành -IL, header của phản hồi 301 sẽ được theo sau lần lượt bởi header của phản hồi 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

Trong sơ đồ dưới đây, bạn có thể so sánh từng bước số lần gửi yêu cầu và những gì hiện trên màn hình với mỗi tùy chọn.

🧭 Yêu cầu và đầu ra theo tùy chọn curl: 301 của địa chỉ http
Sơ đồ giải thích
⚙️ Tùy chọn
$ curl -I -L -IL http://example.com/
① GETHEAD Yêu cầuhttp://example.com/
➜
301 Moved PermanentlyLocation: https://example.com/
② GETHEAD Yêu cầuhttps://example.com/Không gửi yêu cầu
➜
200Không có phản hồi
🖥️ Những gì in ra màn hình
Nội dung phản hồi 301 (7 dòng HTML)
Header phản hồi 301, 7 dòng
Nội dung phản hồi 200 (HTML trang chủ, 96.679 byte)
Header 301, 7 dòng → header 200, 10 dòng
Không có tùy chọn, curl không gửi lại yêu cầu tới địa chỉ https trong [Location] và chỉ in nội dung của phản hồi 301.
-I chỉ nhận header bằng yêu cầu HEAD và, không yêu cầu địa chỉ mới, in trạng thái 301 cùng header [Location].
-L gửi thêm một yêu cầu tới địa chỉ https trong [Location] và in nội dung của phản hồi 200 cuối cùng.
-IL in lần lượt header của cả hai phản hồi. Sau 301 là 200.

3️⃣ Tải tệp bằng lệnh curl (-o, -O)

-O lưu tệp vào thư mục hiện tại với tên tệp cuối cùng trong địa chỉ. Trong lúc lưu, màn hình hiện thanh tiến trình thay cho nội dung.

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

Sau khi tải, [Total] và [Received] trên thanh tiến trình đều là 3113, và kích thước tệp kiểm tra bằng ls -l cũng khớp: 3.113 byte.

Muốn tự đặt tên tệp, bạn viết tên tệp sau -o. Dưới đây là kết quả lưu địa chỉ trang chủ thành 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 dùng nguyên tên tệp ở cuối địa chỉ, nên không hợp với địa chỉ trang kết thúc bằng dấu gạch chéo. Thêm -O vào địa chỉ trang chủ thì curl không tìm được tên tệp và kết thúc với lỗi bên dưới.

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

4️⃣ Yêu cầu POST với curl và gửi dữ liệu JSON

Muốn gửi dữ liệu kèm một yêu cầu trước giờ chỉ đọc, bạn dùng -d, và thêm -H để nêu định dạng dữ liệu. -d gửi dữ liệu viết phía sau làm nội dung POST. Nếu không chỉ định gì thêm, [Content-Type] là [application/x-www-form-urlencoded].

Khi dùng -d, phương thức yêu cầu chuyển thành POST, nên bạn có thể bỏ [-X POST]. Tài liệu chính thức cũng giải thích rằng thường không cần -X.

Khi gửi JSON, dùng -H để đổi [Content-Type] thành [application/json]. Dưới đây là kết quả gửi yêu cầu tạo bài viết tới REST API của WordPress mà không xác thực.

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}}

Trang mà chúng tôi gửi yêu cầu chặn các yêu cầu REST API từ người chưa đăng nhập nên code trả về [rest_authentication_error] và trạng thái là 401. Cũng vì thiết lập đó, yêu cầu GET danh sách bài viết ở cùng địa chỉ cũng trả về 401. Giá trị message là câu báo lỗi viết bằng ngôn ngữ của trang, được chuyển sang dạng Unicode của JSON.

Muốn chỉ xem mã trạng thái, bỏ nội dung bằng [-o /dev/null] và chỉ in http_code bằng -w.

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️⃣ Đo thời gian phản hồi bằng lệnh curl (-w)

Khi phản hồi chậm, người ta dễ chỉ nhìn total, nhưng muốn biết thời gian tốn ở khâu kết nối hay khâu xử lý của máy chủ thì phải in riêng thời gian từng giai đoạn. -w in các giá trị đo theo định dạng bạn chỉ định sau khi yêu cầu kết thúc. Giá trị được điền vào các chỗ [%{tên biến}] trong định dạng.

Bỏ nội dung bằng [-o /dev/null] và ẩn thanh tiến trình bằng -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 là kết nối TCP, tls là quá trình bắt tay TLS, ttfb là thời gian tới ngay trước khi byte đầu tiên được gửi, còn total là thời gian tới khi truyền xong. Cả bốn giá trị đều là số giây cộng dồn từ lúc bắt đầu yêu cầu.

Vì máy chủ chạy curl và trang nhận yêu cầu nằm trên cùng một máy chủ, kết nối chỉ mất 0,0015 giây, bắt tay TLS xong lúc 0,0177 giây và byte đầu tiên tới lúc 0,0219 giây. Từ lúc bắt tay TLS xong tới khi byte đầu tiên tới mất khoảng 0,004 giây. Tài liệu chính thức giải thích rằng giai đoạn này gồm cả thời gian máy chủ tạo kết quả.

Khi chạy cùng lệnh thêm ba lần, total nằm trong khoảng 0,0219 đến 0,0226 giây.

🔲 Trình mô phỏng lệnh curl

Trong trình mô phỏng dưới đây, bạn có thể tự gõ các lệnh đã xem và kiểm tra đầu ra thay đổi thế nào với mỗi tùy chọn.

Trình mô phỏng lệnh curlcurl 7.76.1
[root@server work]#
Dùng phím ↑↓ trên bàn phím để gọi lại các lệnh đã gõ trước đó.

🔢 FAQ & nội dung đề xuất

-s ẩn cả thanh tiến trình lẫn thông báo lỗi. Khi chúng tôi yêu cầu một địa chỉ không tồn tại, không có gì được in ra và chỉ còn mã thoát 6. Nếu chỉ định -sS cùng lúc, thanh tiến trình vẫn ẩn nhưng các lỗi như [curl: (6) Could not resolve host] vẫn hiện ra.

-k bỏ qua bước kiểm tra kết nối có an toàn hay không, nên curl gửi dữ liệu mà không kiểm tra máy chủ đã kết nối có đúng là của tên miền đó. curl kiểm tra chứng chỉ máy chủ có chứa tên miền bạn kết nối tới hay không và có xác minh được bằng kho chứng chỉ hay không. Khi gặp lỗi này, hãy kiểm tra trước tên miền và đơn vị cấp chứng chỉ.

Theo tài liệu chính thức, khi nhận phản hồi 301, 302 hoặc 303, curl đổi yêu cầu tiếp theo sang GET rồi gửi. Muốn giữ POST, hãy dùng các tùy chọn riêng như [--post301]. Phương thức chỉ định bằng -X được ưu tiên hơn việc chuyển đổi này.

🧭 Nội dung đề xuất về lệnh mạng 9 bài viết · 2 tham khảo
🗂️ Lệnh mạng
📄 Lệnh SSH 📄 Lệnh rsync 📄 Lệnh wget 📄 Lệnh rz · sz 📄 Lệnh curl
📄 Lệnh host 📄 Lệnh nslookup
📄 Lệnh ip 📄 Lệnh netstat · ifconfig

ℹ️ Thông báo tiếp thị liên kết
Nội dung trên trang này có chứa liên kết affiliate (tiếp thị liên kết). Khi khách truy cập mua sản phẩm hoặc dịch vụ qua các liên kết này, trang sẽ nhận hoa hồng từ bên bán. Trong quá trình đó, số tiền người mua phải trả (sẽ giảm khi có chương trình khuyến mãi ↓) không hề tăng lên. Giá, khuyến mãi và tình trạng hàng được đăng theo thời điểm viết bài và có thể khác với thực tế, vì vậy hãy kiểm tra lại lần cuối với bên bán trước khi mua. Việc chọn và đánh giá sản phẩm dựa trên tiêu chí riêng của trang; việc có nhận hoa hồng hay không không ảnh hưởng đến thứ tự giới thiệu hay nội dung đánh giá.

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Prove your humanity: 10   +   7   =