127.0.0.1 SỔ TAY VẬN HÀNH MÁY CHỦ & CỨU HỘ WORDPRESS THỰC CHIẾN
MINH BẠCH

Ổ đĩa VPS đầy 100%: Khoanh vùng thủ phạm bằng df -h, du -sh, Inode và lsof trước khi xóa

Hướng dẫn dùng df -h, df -i, du -sh và lsof tìm thủ phạm làm đầy ổ đĩa VPS: phân biệt log, backup, dữ liệu MariaDB và file đã xóa nhưng vẫn đang mở.

Tối ưu VPS // localhost.vn
Mục lục bài viết (15 mục)
ĐÚC KẾT THỰC CHIẾN

Thấy ổ đĩa báo đỏ 100% mà nhắm mắt gõ rm -rf vào file to nhất thì dễ tiễn luôn MariaDB về nơi chín suối: hãy dùng df -h, df -i, du và lsof để bắt đúng thủ phạm trước khi dọn.

Hồ sơ thực nghiệm trên lab: Tiến hành khảo sát dung lượng ổ đĩa, chỉ số Inode, phân bổ các nhánh thư mục /var và danh sách file đang mở trên máy chủ LAB-CF-02 vào ngày 01/10/2026. Do phân vùng gốc ext4 chứa WordPress vẫn còn trống nhiều, chúng tôi đã dựng một phân vùng ảo tmpfs giới hạn 16 MiB trong không gian cô lập để diễn tập tình huống đầy đĩa 100% (ENOSPC), chứng minh hiện tượng xóa file nhưng tiến trình còn giữ descriptor làm df không giảm, sau đó giải phóng dung lượng và xác minh cơ chế WordPress sideload cùng thao tác ghi bài nháp hoạt động trở lại bình thường (rồi hoàn tác giao dịch trên bản clone). Lưu ý rằng vùng dữ liệu của MariaDB không bị ép đầy thực tế để bảo toàn hệ thống.

Trong cuộc đời làm sysadmin hay quản trị VPS WordPress, chắc chắn sẽ có một buổi sáng đẹp trời bạn nhận được tin nhắn cầu cứu: “Anh ơi web không đăng bài được, upload ảnh toàn báo lỗi, mà tự nhiên database cũng đơ luôn!”. Mở terminal lên gõ nhẹ một lệnh thấy cột Use% chạm mốc 100%. Lúc này, sai lầm chí mạng nhất của những cái đầu nóng là tìm xem file nào nặng vài chục GB rồi phang thẳng tay lệnh rm -rf cho lẹ. Khoan đã nào! Nhỡ cái thư mục log bạn vừa xóa trắng đang giữ bằng chứng duy nhất của một cuộc tấn công, hoặc tệ hơn là bạn vừa thẳng tay xóa mất file ibdata1 hay ib_logfile của MariaDB chỉ vì thấy nó to nhất trong /var/lib/mysql thì sao? Chấp nhận để website tạm ngừng nhận upload thêm 10 phút để điều tra đúng quy trình vẫn tốt hơn gấp vạn lần việc giải phóng được 20 GB ổ cứng nhưng làm hỏng vĩnh viễn toàn bộ cơ sở dữ liệu khách hàng.

Bài viết này sẽ hướng dẫn anh em từng bước dùng các câu lệnh đọc an toàn trong phạm vi hẹp để chỉ mặt đặt tên chính xác: dữ liệu nào đang ngốn chỗ, dịch vụ nào làm chủ nó, và làm sao để thu hồi dung lượng một cách êm ái nhất. Khi chưa nắm rõ vòng đời của một tập tin, tuyệt đối không chạy lệnh xóa đệ quy mù quáng hay gõ docker system prune -a --volumes theo kiểu cầu may.

Điều kiện cần chuẩn bị trước khi thực hành

Để thực hành trơn tru, bạn cần có quyền quản trị trên một máy lab riêng và đã nắm vững kiến thức nền tảng từ lộ trình cài WordPress trên VPS từ A đến Z. Môi trường chuẩn trong bài viết sử dụng Ubuntu 24.04 LTS, NGINX, PHP 8.3 và MariaDB 10.11. Hãy đối chiếu lại phiên bản phần mềm, tên systemd service và cấu trúc đường dẫn trên máy thử nghiệm của bạn trước khi thực thi, bởi mỗi cách phân chia phân vùng thực tế sẽ cho kết quả khác nhau.

Nguyên tắc an toàn quen thuộc: hãy thao tác trên dữ liệu giả lập, dùng tài khoản tách biệt và đặt thư mục thử nghiệm nằm ngoài vùng dữ liệu đang phục vụ người dùng. Các biến môi trường viết hoa cần được điền bằng giá trị đã xác minh trên lab; tuyệt đối không lưu mật khẩu hay thông tin nhạy cảm vào bài viết, lịch sử gõ lệnh shell (~/.bash_history) hoặc kho mã nguồn. Nếu gặp thông báo “command not found”, hãy bình tĩnh cài đặt gói công cụ tương ứng theo tài liệu chính thức của hệ điều hành — thiếu công cụ kiểm tra không có nghĩa là website bị lỗi. Các sơ đồ kỹ thuật trong bài giúp tóm tắt quy trình xử lý, đi kèm với bộ ảnh chụp màn hình console thực tế ở phần sau.

Đọc trước khi dọn: Filesystem bị đầy; Dung lượng còn; Inode còn; Lỗi ghi của ứng dụng

Sơ đồ kỹ thuật 1: Bốn yếu tố cần đọc kỹ để định vị đúng phân vùng đang gặp sự cố trước khi dọn dẹp. Sơ đồ do đội ngũ localhost.vn biên soạn.

Xác định đúng phân vùng Filesystem và phân biệt hết GB với hết Inode

Bước đầu tiên khi nghe tin ổ cứng đầy là chạy ngay cặp lệnh kiểm tra dung lượng khối (block storage) và bảng chỉ mục tập tin (Inode), đồng thời xác định xem thư mục chứa mã nguồn webroot, thư mục dữ liệu /var/lib/mysql của MariaDB và thư mục chứa các bản sao lưu (backup) đang nằm trên cùng một phân vùng hay tách ra nhiều volume khác nhau. Nếu database nằm trên ổ /dev/vdb1 đang đầy 100%, mà bạn lại hì hục đi xóa file rác ở ổ /dev/vda1 đang trống mênh mông thì chẳng giải quyết được tích sự gì cả!

df -hT
df -i

Khi nhìn bảng kết quả của df -hT và df -i, hãy đọc song song cả cột phần trăm đã dùng (Use% / IUse%) lẫn con số dung lượng tuyệt đối còn trống (Avail / IFree). Có hai kiểu “chết nghẹt” rất khác nhau trên Linux: kiểu thứ nhất là một vài file khổng lồ (như file quên tắt WP_DEBUG_LOG hoặc bản nén backup .tar.gz) nuốt trọn toàn bộ số GB của ổ đĩa; kiểu thứ hai hiểm hóc hơn là hàng triệu file nhỏ li ti (như file session PHP bị kẹt hoặc cache rác) ăn sạch 100% số lượng Inode dù dung lượng ổ cứng vẫn còn thừa cả chục GB. Ngoài ra, ngay cả khi df báo mới dùng 95% và chưa chạm đỉnh 100%, các tiến trình chạy dưới quyền user thường (như www-data hoặc mysql) vẫn có thể bị từ chối ghi dữ liệu kèm lỗi No space left on device — nguyên nhân là do hệ thống tập tin ext4 mặc định dành riêng khoảng 5% dung lượng (reserved blocks) chỉ cho tài khoản root sử dụng để cứu hộ hệ thống khi khẩn cấp!

Khoanh vùng thư mục phình to bằng lệnh du (du -sh / du -xhd1) có điểm dừng

Sau khi đã biết chắc phân vùng nào đang kêu cứu, hãy bắt đầu khoanh vùng từ thư mục /var hoặc điểm gắn kết (mount point) tương ứng. Kinh nghiệm xương máu của đàn anh là luôn gắn kèm cờ -x (--one-file-system) để lệnh du không đi lạc sang các phân vùng filesystem khác (như /proc, /sys hay ổ mạng mount thêm), kết hợp với cờ -d 1 (--max-depth=1) hoặc du -sh để bóc tách từng tầng thư mục từ trên xuống dưới, thấy nhánh nào to bất thường mới đào sâu tiếp vào nhánh đó.

sudo du -xhd1 /var
sudo du -xhd1 /var/log
sudo du -xhd1 /var/lib
sudo journalctl --disk-usage

Lưu ý về mặt hiệu năng Disk I/O: nếu một thư mục chứa hàng triệu tập tin nhỏ, việc chạy lệnh du quét qua toàn bộ cây thư mục sẽ bắt ổ cứng đọc metadata liên tục và có thể làm treo đơ website nếu chạy vào giờ cao điểm! Vì vậy, tuyệt đối không bật 3–4 cửa sổ terminal chạy du / song song cùng lúc, và đừng dùng tiểu xảo 2>/dev/null để giấu nhẹm luồng báo lỗi chuẩn (stderr). Nếu du văng thông báo Permission denied ở thư mục nào, hãy ghi nhận lại đường dẫn đó cùng mã thoát: con số tổng mà du cộng được lúc đó mới chỉ phản ánh những thư mục nó được phép đọc, chưa phải toàn bộ sự thật. Và đừng hoảng hốt nếu thấy tổng dung lượng của du nhỏ hơn hẳn con số đã dùng trong df — đó không phải do công cụ tính sai đâu, mà là dấu hiệu kinh điển dẫn chúng ta tới bước điều tra ngay sau đây.

Khoanh nguyên nhân: du theo một tầng; Log và backup; Dữ liệu MariaDB; File xóa còn mở

Sơ đồ kỹ thuật 2: Quy trình khoanh vùng thủ phạm gây đầy đĩa từ tầng thư mục xuống tới các tiến trình ngầm. Sơ đồ do đội ngũ localhost.vn biên soạn.

Truy lùng những “bóng ma” ngốn ổ cứng: File đã xóa nhưng tiến trình vẫn giữ mở (lsof +L1)

Đây là tình huống làm đau đầu không biết bao nhiêu quản trị viên: bạn phát hiện file access.log hoặc error.log nặng 20 GB, bạn hăm hở gõ rm /var/log/nginx/error.log, xóa xong gõ du -sh thấy thư mục nhẹ bẫng, nhưng gõ df -h thì ổ cứng vẫn báo đầy 100% không giảm một megabyte nào! Tại sao lại có chuyện ma quái thế? Trên hệ điều hành Linux, lệnh rm thực chất chỉ xóa cái tên đường dẫn (unlink) khỏi danh mục thư mục; chừng nào tiến trình đang chạy (như NGINX, PHP-FPM hay MariaDB) vẫn còn giữ file descriptor mở trỏ tới vùng dữ liệu đó, nhân hệ điều hành sẽ chưa bao giờ thu hồi các khối dữ liệu (blocks) trên ổ đĩa. Để bắt tận tay những tập tin đã bị xóa tên nhưng vẫn âm thầm chiếm chỗ (có số liên kết link count < 1), hãy dùng ngay công cụ lsof với câu lệnh chỉ đọc cực kỳ lợi hại dưới đây:

sudo lsof +L1

Khi danh sách hiện ra, hãy bình tĩnh đối chiếu cột mã tiến trình (PID), tên dịch vụ (COMMAND), dung lượng chiếm dụng (SIZE/OFF) và đường dẫn file kèm nhãn (deleted) trước khi quyết định ra tay; tuyệt đối không nhắm mắt gõ kill -9 bừa bãi! Để giải phóng không gian đĩa một cách văn minh, bạn chỉ cần yêu cầu dịch vụ đó mở lại file log mới (ví dụ gửi tín hiệu USR1 hoặc chạy nginx -s reopen / systemctl reload nginx), hoặc lên lịch khởi động lại tiến trình đó vào khung giờ thấp điểm. Đó cũng là lý do vì sao khi cấu hình công cụ xoay vòng nhật ký (logrotate) cho NGINX hay PHP-FPM, người ta luôn phải kèm theo kịch bản postrotate để báo cho dịch vụ biết mà nhả file cũ ra.

Xử lý đúng cách theo từng “chủ nhân” của dữ liệu

Mỗi loại dữ liệu trên VPS có một quy tắc dọn dẹp riêng biệt, không thể dùng chung một cây búa rm cho tất cả. Đối với các bản sao lưu cũ (/var/backups hoặc thư mục backup tự tạo), trước khi xóa bớt các bản quá hạn (retention), hãy kiểm tra kỹ mã băm SHA-256 và chắc chắn rằng bạn đã có ít nhất một bản sao lưu hoàn chỉnh nằm an toàn ở kho lưu trữ ngoài máy chủ (offsite storage). Đối với bộ nhớ đệm (cache) của WordPress hoặc NGINX FastCGI Cache, hãy ưu tiên dùng tính năng Purge Cache chính thống của plugin hoặc WP-CLI. Còn với nhật ký hệ thống systemd-journald, hãy kiểm tra dung lượng thực tế rồi dùng lệnh journalctl --vacuum-size=... hoặc cấu hình giới hạn trong journald.conf; nhớ rằng lệnh vacuum chỉ dọn các file journal đã đóng gói lưu trữ (archived), chứ không xóa ngang file journal đang ghi dở.

Đặc biệt khắc cốt ghi tâm nguyên tắc bất khả xâm phạm đối với cơ sở dữ liệu: Tuyệt đối không bao giờ dùng lệnh rm của Linux để xóa các file ibdata1, ib_logfile*, bảng .ibd hay các file nhật ký nhị phân (mysql-bin.* / binary log) bên trong /var/lib/mysql! Nếu thư mục MariaDB phình to do binary log, bạn phải kiểm tra xem hệ thống có đang chạy đồng bộ bản sao (Replication) hay phục vụ khôi phục theo thời điểm (PITR) hay không, rồi dùng câu lệnh SQL chuẩn là PURGE BINARY LOGS từ bên trong MariaDB để cơ sở dữ liệu tự cập nhật lại file chỉ mục một cách an toàn. Tương tự, nếu ổ cứng đầy nhanh do một lỗi code PHP lặp vô tận bắn hàng triệu dòng vào log mỗi phút, bạn phải sửa cái lỗi code đó trước rồi mới dọn log — bằng không bạn vừa dọn xong đi pha cốc cà phê quay lại thì ổ cứng đã đầy 100% như cũ!

Xác minh khả năng ghi dữ liệu của WordPress và theo dõi tốc độ tăng trưởng

Sau khi đã giải phóng được dung lượng, đừng vội phủi tay tắt máy ngay. Hãy chạy lại cặp lệnh df -hT, df -i và du trên đúng phạm vi vừa xử lý để ghi nhận con số đối chứng. Tiếp theo, hãy thử tải lên một tấm ảnh nhỏ hoặc tạo một bản nháp bài viết trong WordPress rồi kiểm tra lại log của NGINX, PHP-FPM và MariaDB xem mọi thao tác đọc/ghi đã thực sự mượt mà trở lại chưa. Lưu ý rằng nếu trước đó ổ đĩa cạn kiệt tới mức làm MariaDB bị sập giữa chừng khi đang ghi giao dịch, thì việc có lại vài GB ổ trống mới chỉ là điều kiện cần đầu tiên; bạn bắt buộc phải kiểm tra trạng thái toàn vẹn của các bảng dữ liệu trước khi yên tâm mở cửa đón khách.

Hãy tập thói quen ghi vào sổ tay vận hành dung lượng trước và sau khi dọn kèm mốc thời gian chuẩn, danh mục dữ liệu đã thu hồi và nơi lưu giữ bản sao dự phòng. Đồng thời, hãy cài đặt cảnh báo sớm dựa trên tốc độ phình to của ổ đĩa (disk fill rate). Nếu qua theo dõi nhiều tuần mà thấy dữ liệu tăng lên là do nội dung bài viết và hình ảnh sản phẩm thật của website ngày càng nhiều, thì giải pháp đúng đắn là rút hầu bao nâng cấp thêm dung lượng ổ cứng VPS hoặc đẩy thư viện ảnh sang Object Storage (như S3 / Cloudflare R2), chứ không phải suốt ngày ngồi canh xóa từng megabyte.

Tiêu chuẩn nghiệm thu và sự trung thực với số liệu đo đạc

Một biên bản xử lý sự cố đầy đĩa đạt chuẩn cần chỉ rõ tên phân vùng (mount point), số lượng Inode, thư mục nguyên nhân gốc rễ và bằng chứng xác nhận ứng dụng đã ghi dữ liệu thành công sau khi dọn. Chưa đo đạc đối chiếu trước–sau trên cùng một hệ quy chiếu thì tuyệt đối không phát ngôn kiểu ước chừng “đã dọn sạch 50% rác”. Nếu trong lúc chạy du có những thư mục bị từ chối quyền đọc hoặc có tiến trình khác đang đồng thời ghi/xóa file làm con số biến động, hãy ghi chú rõ giới hạn đó, tránh việc lấy các con số đo ở những thời điểm khác nhau rồi cộng trừ cơ học.

Xử lý có hậu kiểm: Đúng công cụ dữ liệu; Giữ bản cần phục hồi; Đo lại cùng mount; Thử thao tác ghi

Sơ đồ kỹ thuật 3: Bốn bước xử lý an toàn và kiểm tra nghiệm thu khả năng ghi dữ liệu sau khi thu hồi dung lượng. Sơ đồ do đội ngũ localhost.vn biên soạn.

Bản ghi khảo sát dung lượng thực tế trên LAB-CF-02 ngày 01/10/2026

Biên bản khảo sát dung lượng phân vùng và kiểm tra các tập tin đang mở dưới đây được thực hiện trên máy chủ LAB-CF-02 vào khung giờ 00:21:30–00:21:35 (UTC+7). Toàn bộ thư mục mã nguồn webroot, thư mục dữ liệu MariaDB và kho lưu trữ sao lưu nội bộ đều nằm chung trên phân vùng /dev/vda1, định dạng ext4, gắn tại điểm mount gốc /. Kết quả lệnh df -hT báo tổng dung lượng 38G, đã sử dụng 2.7G, còn trống 36G (tỷ lệ dùng 8%); bảng chỉ mục Inode mới dùng 94.132 trên tổng số 5.111.808 (tương đương 2%). Như vậy, ổ cứng chính của máy lab đang ở trạng thái rất thông thoáng, chưa hề bị đầy.

Tiếp theo, ba câu lệnh du được chạy tuần tự để khảo sát từng nhánh /var, /var/log và /var/lib (không quét toàn bộ ổ đĩa song song). Luồng báo lỗi chuẩn stderr được giữ nguyên để giám sát và cả ba lệnh đều hoàn tất trơn tru với mã thoát exit 0, không gặp bất kỳ lỗi phân quyền nào.

Phạm vi thư mục khảo sát Dung lượng hiển thị qua lệnh du -h
Tổng nhánh /var 1.1G
Nhánh bộ nhớ đệm /var/cache 372M
Nhánh dữ liệu /var/lib 370M (trong đó thư mục apt chiếm 200M, còn mysql chiếm 129M)
Nhánh mã nguồn web /var/www 256M
Nhánh sao lưu /var/backups 42M
Nhánh nhật ký /var/log 19M (trong đó riêng thư mục journal chiếm 17M)

Khi đọc bảng số liệu trên, cần lưu ý các đơn vị G và M được làm tròn theo cơ số lũy thừa 1024 của cờ -h (human-readable). Tuyệt đối không lấy dung lượng của thư mục con cộng dồn vào thư mục cha (vì /var đã bao hàm tất cả các nhánh bên dưới rồi). Một chi tiết thú vị khác: lệnh journalctl --disk-usage báo dung lượng nhật ký là 16.0M, trong khi lệnh du /var/log/journal lại hiển thị 17M — sự chênh lệch nhỏ này hoàn toàn bình thường do hai công cụ tính toán phần kích thước khối (block allocation) và metadata của thư mục theo cách khác nhau, không phải dấu hiệu lỗi hệ thống và cũng không được cộng gộp hai con số này lại.

Ở bước quét các tập tin đã xóa tên nhưng còn giữ mở bằng lệnh lsof -nP +L1, hệ thống trả về 8 dòng descriptor: bao gồm 4 dòng của tiến trình PHP-FPM trỏ tới vùng nhớ chia sẻ memfd:opcache_lock và 4 dòng file tạm nội bộ của MariaDB. Cả 8 dòng này đều có chỉ số liên kết NLINK = 0 và kích thước SIZE/OFF = 0 byte. Đây là cơ chế hoạt động hoàn toàn bình thường của Zend OPcache và MariaDB khi tạo vùng nhớ/file tạm ẩn danh để tự động dọn dẹp khi tiến trình kết thúc, chứ không phải 8 cục rác khổng lồ cần bạn phải vào giải cứu! Do đó, đừng thấy có dòng xuất hiện trong lsof +L1 mà vội vàng kết luận dịch vụ bị rò rỉ dung lượng hay đè ra khởi động lại.

Trong các nhánh con của /var ở đợt đo này, thư mục /var/cache đứng đầu bảng về dung lượng (372M), nhưng con số lớn nhất không đồng nghĩa với việc bạn cứ thế nhảy vào xóa bừa. Đợt khảo sát lúc 00:21 hoàn toàn chỉ đọc thông tin, không can thiệp vào dữ liệu DB hay backup, không xóa file và không restart bất kỳ dịch vụ nào. Để diễn tập thực tế kịch bản ổ đĩa chạm đáy 100% mà không gây nguy hiểm cho phân vùng ext4 đang chạy WordPress, chúng tôi đã thiết kế hai bài thực nghiệm cô lập trên tmpfs vào lúc 10:16 và 10:35 ngay dưới đây.

Đối chiếu lại dung lượng đĩa và danh sách lsof lúc 10:14–10:15

Vào lúc 10:14:03 ngày 01/10/2026 (UTC+7), chúng tôi thực hiện đợt kiểm tra đối chứng thứ hai trên LAB-CF-02. Ba đường dẫn cốt lõi gồm webroot, MariaDB và thư mục backup vẫn nằm trên phân vùng /dev/vda1 (ext4, mount tại /) với tổng dung lượng 38G, mức đã dùng nhích nhẹ lên 2.9G, còn trống 35G (vẫn giữ mức 8%). Số lượng Inode đã dùng là 125.661 trên tổng 5.111.808, còn trống 4.986.147 (tương ứng mức 3%).

Console LAB-CF-02 ngày 01/10: CPU, RAM available, đĩa ext4 dùng 8%, inode 3% và năm khoảng vmstat

Ảnh chụp màn hình terminal thực tế của đợt kiểm tra bắt đầu lúc 10:14:03 ngày 01/10/2026 (UTC+7); giữ nguyên từng pixel vùng dữ liệu console kèm logo nhận diện. Tập lệnh tự động gọi các công cụ kiểm tra và in nhãn phân tách rõ ràng. Lưu ý dòng đầu tiên của vmstat phản ánh giá trị trung bình từ lúc boot cho phần CPU/I/O, trong khi bộ nhớ và tiến trình là con số tức thời. Bấm vào ảnh để xem kích thước đầy đủ.

Ngay tiếp sau đó, vào lúc 10:15:01 (UTC+7), phép đo phân bổ dung lượng theo từng nhánh thư mục ghi nhận kết quả như sau:

Phạm vi thư mục khảo sát Dung lượng hiển thị lúc 10:15
Tổng nhánh /var 1007M
Nhánh dữ liệu /var/lib 440M
Nhánh mã nguồn web /var/www 256M
Nhánh bộ nhớ đệm /var/cache 182M
Nhánh sao lưu /var/backups 85M
Nhánh nhật ký /var/log 47M
Dung lượng Journal qua journalctl --disk-usage 36.7M

Cũng giống như lần đo trước, các con số đều giữ nguyên định dạng làm tròn của công cụ xuất dữ liệu. Nhắc lại nguyên tắc: không lấy dung lượng của /var cộng thêm các thư mục con bên trong, và không cộng chồng con số 36.7M của journal vào tổng dung lượng 47M của /var/log.

Console LAB-CF-02 lúc 10:15 ngày 01/10: du các nhánh var, journal 36.7M và lsof liệt kê file đã unlink còn mở

Ảnh chụp màn hình console thực tế của đợt khảo sát chỉ đọc bắt đầu lúc 10:15:01 (UTC+7), giữ nguyên độ phân giải gốc kèm logo. Tập lệnh gọi tuần tự du, journalctl và lsof mà không thực hiện bất kỳ thao tác xóa file hay khởi động lại dịch vụ nào. Bấm vào ảnh để xem rõ toàn bộ nội dung.

Đáng chú ý, kết quả lệnh lsof lúc 10:15 xuất hiện 10 dòng dữ liệu: bên cạnh 4 dòng file tạm MariaDB và 3 dòng PHP memfd có kích thước bằng 0 như thường lệ, lần này xuất hiện thêm 3 file thực thi (executable binaries) mang trạng thái đã bị unlink gồm systemd-logind (285.264 byte), trình thông dịch Python (8.019.136 byte) và agetty (60.992 byte). Hiện tượng này thường xảy ra rất tự nhiên trên Linux ngay sau khi hệ thống vừa chạy cập nhật gói phần mềm (apt upgrade): gói mới ghi đè file binary mới lên đĩa và xóa bản cũ đi, nhưng các tiến trình dịch vụ đang chạy từ trước vẫn giữ tham chiếu tới bản binary cũ trong bộ nhớ cho tới khi chúng được khởi động lại. Vì nhiều tiến trình hoặc luồng có thể cùng trỏ vào một file thực thi duy nhất, bạn không được lấy kích thước các dòng trong lsof cộng dồn cơ học lại, và càng không bao giờ tự động kill bừa tiến trình hệ thống chỉ vì thấy nó xuất hiện trong danh sách này.

Thực nghiệm lấp đầy phân vùng ảo tmpfs 16 MiB lúc 10:16: Chứng minh sự lệch pha giữa du và df

Vào lúc 10:16:52 ngày 01/10/2026 (UTC+7), trên máy chủ LAB-CF-02, chúng tôi khởi tạo một môi trường thử nghiệm cực kỳ an toàn bằng cách tạo một phân vùng tmpfs giới hạn đúng 16 MiB nằm gọn bên trong một không gian gắn kết cô lập (mount namespace riêng biệt với cờ propagation private thông qua lệnh unshare). Nhờ nằm trên bộ nhớ ảo và hoàn toàn tách rời khỏi ổ cứng ext4 đang chứa WordPress, chúng ta có thể thoải mái bơm dữ liệu kịch trần để quan sát mã lỗi đầy đĩa của nhân Linux mà không làm ảnh hưởng một sợi tóc nào tới các dịch vụ bên ngoài.

Giai đoạn trong kịch bản thực nghiệm Hiện tượng và số liệu quan sát được
1. Ghi dữ liệu chạm trần giới hạn Ghi đủ 16.777.216 byte (đúng 16 MiB) thì lập tức văng mã lỗi hệ thống errno 28 (ENOSPC - No space left on device); lệnh df báo mức sử dụng chạm đỉnh 100%
2. Xóa tên file (unlink) nhưng vẫn giữ mở file descriptor Lệnh du lập tức tụt về 0, nhưng lệnh df vẫn đứng im ở mức 100%; công cụ lsof bắt quả tang dòng file có NLINK=0 và kích thước SIZE/OFF=16777216
3. Tiến trình chủ động đóng file descriptor Ngay khoảnh khắc descriptor được đóng lại, dung lượng đã dùng trên df lập tức giải phóng về 0
4. Kiểm tra ghi lại dữ liệu mới Tạo và đọc đối chứng thành công một file thử nghiệm nặng 20 byte; lệnh df -k báo đang dùng 4 KiB (hiển thị làm tròn là 1%)
5. Thu dọn môi trường thử nghiệm Xóa bỏ file/thư mục thử nghiệm và gỡ gắn kết (unmount) phân vùng tmpfs; không gian mount của hệ thống chính bên ngoài hoàn toàn không bị tác động

Console tóm tắt phép thử tmpfs 16 MiB: đầy ENOSPC, file unlink còn mở giữ dung lượng, đóng descriptor rồi ghi lại thành công

Ảnh chụp màn hình console thực tế lúc 10:17:27 ngày 01/10/2026 (UTC+7), giữ nguyên độ phân giải gốc kèm logo nhận diện. Tập lệnh thực nghiệm chạy trực tiếp các bước từ gây đầy đĩa ENOSPC đến giữ mở descriptor rồi đóng lại và in bản tóm tắt kết quả (mốc thời gian 03:16:52 UTC trong ảnh tương ứng chính xác với 10:16:52 giờ Việt Nam). Bấm vào ảnh để xem chi tiết.

Bằng chứng thực nghiệm trên đã tái hiện sống động ngay trước mắt bạn bài toán kinh điển của giới quản trị hệ thống Linux: tại sao xóa file xong mà du báo hết nhưng df vẫn báo đầy 100%! Chỉ khi tiến trình đang ôm khư khư cái file descriptor đó chịu nhả ra (đóng file hoặc reload dịch vụ), nhân Linux mới thực sự trả lại không gian trống cho phân vùng. Trong kịch bản này, chính tập lệnh thử nghiệm đã tự đóng descriptor do nó mở ra, hoàn toàn không đụng chạm tới bất kỳ tiến trình dịch vụ nào khác trên máy chủ.

Tuy nhiên, việc ghi lại thành công một tập tin văn bản 20 byte ở tầng hệ điều hành mới chỉ chứng minh phân vùng đã nhận dữ liệu trở lại, chứ chưa trả lời được câu hỏi: bản thân ứng dụng WordPress phản ứng ra sao khi kho chứa ảnh bị đầy và lúc vừa được giải phóng? Đó chính là lý do chúng tôi thực hiện tiếp phiên thực nghiệm ở tầng ứng dụng WordPress vào lúc 10:35 ngay bên dưới.

Thực nghiệm phản ứng của WordPress khi đầy đĩa và sau khi giải phóng dung lượng (Phiên 10:35)

Vào lúc 10:35:43–10:35:44 ngày 01/10/2026 (UTC+7) trên môi trường bản sao (clone), chúng tôi sử dụng bộ lọc (filter hook) trong phạm vi một tiến trình chạy WP-CLI dưới quyền user www-data (UID 33) để tạm thời bẻ hướng đường dẫn thư mục tải lên (upload_dir) sang phân vùng tmpfs 16 MiB cô lập, giữ nguyên vẹn thư mục wp-content/uploads thật của website bên ngoài. Hàm xử lý tải file chuẩn của lõi WordPress là wp_handle_sideload được gọi trực tiếp để kiểm tra khả năng ghi tập tin đa phương tiện vào thư mục đích.

Hạng mục kiểm chứng trên WordPress Kết quả ghi nhận thực tế
1. Khi phân vùng tmpfs bị lấp đầy 100% Bơm 16.777.216 byte chạm ngưỡng ENOSPC (dung lượng trống bằng 0 KiB); gọi hàm WordPress sideload lập tức thất bại và trả về đối tượng lỗi
2. Ngay sau khi xóa file gây đầy đĩa Dung lượng trống phục hồi về mức 16.384 KiB; gọi lại hàm sideload với một ảnh PNG nặng 75 byte thành công mỹ mãn, mã băm SHA-256 của file sau khi lưu khớp 100% với file gốc
3. Kiểm tra thao tác ghi bài viết nháp vào Database Hàm wp_insert_post tạo bài nháp thành công; truy vấn trực tiếp vào MariaDB xác nhận tiêu đề và trạng thái draft đã được lưu chuẩn xác
4. Hoàn tác giao dịch thử nghiệm (Rollback) Thực thi lệnh ROLLBACK để rút lại bản ghi nháp vừa chèn, tổng số dòng trong bảng wp_posts trở về nguyên trạng ban đầu; riêng bộ đếm tự tăng AUTO_INCREMENT nhích từ 6 lên 7
5. Kiểm tra nghiệm thu toàn hệ thống Thư mục và phân vùng tmpfs thử nghiệm đã được gỡ sạch; không gian mount gốc cùng mã băm các file cấu hình không đổi; cả website gốc lẫn bản clone đều phản hồi HTTP 200

Ở bước 1 khi đĩa đầy, thông báo lỗi nguyên văn tiếng Việt mà lõi WordPress trả về trong cấu trúc JSON là: “Tập tin được tải không thể chuyển tới uploads.” (Do phông chữ mặc định trên cửa sổ terminal chụp ảnh thiếu một vài ký tự dấu tiếng Việt nên chúng tôi trích dẫn nguyên văn tại đây để bạn đọc dễ đối chiếu mà không can thiệp chỉnh sửa pixel của ảnh chụp).

Console LAB-CF-02 tóm tắt WordPress sideload thất bại khi tmpfs đầy, thành công sau giải phóng và kiểm ghi bài nháp rồi rollback

Ảnh chụp màn hình console thực tế lúc 10:35:59 ngày 01/10/2026 (UTC+7), giữ nguyên từng pixel vùng dữ liệu kèm logo nhận diện. Tập lệnh thực nghiệm chạy trực tiếp chuỗi sự kiện lúc 03:35:43–44 UTC (tức 10:35:43–44 giờ Việt Nam). Một vài chữ cái tiếng Việt có dấu bị lỗi hiển thị glyph do bộ phông chữ của terminal. Bấm vào ảnh để phóng to toàn màn hình.

Cần lưu ý sự chuẩn xác về mặt kỹ thuật cơ sở dữ liệu: trong engine InnoDB của MariaDB, một khi bộ đếm AUTO_INCREMENT đã cấp phát số ID mới cho câu lệnh INSERT thì ngay cả khi bạn gọi ROLLBACK để hủy bỏ giao dịch đó, con số tự tăng vẫn tiến lên từ 6 thành 7 chứ không lùi lại. Ngoài ra, trong bài thực nghiệm này, vùng lưu trữ của MariaDB hoàn toàn không bị ép đầy; việc tạo bài nháp thành công chỉ xác nhận luồng ghi dữ liệu hoạt động tốt, chứ không phải là bài diễn tập cứu hộ cơ sở dữ liệu bị hỏng bảng (corrupted tablespace) sau sự cố sập nguồn hay cạn sạch ổ đĩa. Tương tự, việc gọi hàm wp_handle_sideload qua CLI giúp kiểm chứng gọn gàng tầng xử lý file của WordPress, nhưng chưa bao gồm bước đẩy form multipart/form-data qua trình duyệt, cắt ảnh thu nhỏ (thumbnails) bằng thư viện Imagick/GD hay hiển thị trên giao diện Media Library.

Trong thực tế, sau khi bạn vừa giải cứu một con VPS thoát khỏi cảnh đầy ổ đĩa 100%, quy trình nghiệm thu chuẩn mực trên giao diện người dùng sẽ là: mở trình duyệt đăng nhập vào wp-admin, tải thử một tấm ảnh nhỏ qua Media Library, bấm xem cả ảnh gốc lẫn các kích thước ảnh thumbnail xem có bị lỗi trắng ảnh không, sau đó tạo thử một bài viết nháp, bấm Lưu rồi mở lại xem nội dung có còn nguyên vẹn không. Song song đó, hãy mở log của NGINX, PHP-FPM và đặc biệt là log của MariaDB để chắc chắn không còn dòng báo lỗi ghi đĩa nào xuất hiện. Khi mọi thứ đã qua bài kiểm tra ngon lành, bạn mới tiến hành xóa nốt các file kiểm tra vừa tạo.

Nguyên tắc an toàn khi ổ đĩa cạn kiệt và cách tránh làm hỏng dữ liệu

Một cái bẫy cực kỳ ngớ ngẩn mà anh em lúc hoảng loạn rất hay mắc phải: thấy ổ đĩa đang đầy 99%, muốn xóa bớt thư mục cũ nhưng sợ mất dữ liệu nên gõ lệnh tar -czf backup.tar.gz ... để nén lại ngay trên chính cái ổ đĩa đang đầy đó — kết quả là file nén chạy được nửa đường thì lấp đầy nốt 1% cuối cùng, làm sập luôn toàn bộ máy chủ và sinh ra thêm một cục file nén hỏng không dùng được! Nếu ổ đĩa không còn đủ khoảng trống an toàn để tạo bản sao lưu tại chỗ, hãy đẩy luồng dữ liệu sao lưu trực tiếp qua mạng (ví dụ qua đường ống ssh / rsync sang máy khác hoặc đẩy lên Object Storage) trước khi xóa.

Nguyên tắc vàng: nếu nhìn vào một tập tin lạ mà bạn chưa trả lời được nó thuộc về dịch vụ nào và xóa đi có làm sập ứng dụng hay không, hãy dừng ngay ở bước điều tra và tra cứu tài liệu trước. Hãy nhớ rằng lệnh rm trên Linux không có thùng rác (Recycle Bin) để bấm nút Undo đâu; dữ liệu một khi đã xóa khỏi đĩa chỉ có thể lấy lại được nếu bạn đã chuẩn bị sẵn bản sao lưu từ trước hoặc đó là dữ liệu tạm (cache) mà ứng dụng có khả năng tự tái tạo lại.

Câu hỏi thường gặp (FAQ)

Khi ổ đĩa đầy, có nên tìm file nào dung lượng lớn nhất rồi chạy lệnh rm xóa ngay cho nhanh không?

Tuyệt đối không! Kích thước file lớn hoàn toàn không có nghĩa đó là file rác được phép xóa. Rất nhiều trường hợp file lớn nhất trên VPS chính là bảng dữ liệu lõi ibdata1 của MariaDB hoặc gói lưu trữ quan trọng — xóa nhầm một cái là bạn tự tay phá hủy toàn bộ website. Hãy luôn xác định rõ dịch vụ chủ quản và vai trò của tập tin trước khi đụng vào.

Tại sao tôi đã xóa bớt file nặng cả chục GB rồi mà gõ lệnh df -h thấy dung lượng đã dùng vẫn không hề giảm xuống?

Nguyên nhân phổ biến nhất là tập tin đó tuy đã bị xóa tên khỏi thư mục (unlink) nhưng vẫn đang bị một tiến trình đang chạy (như NGINX, PHP-FPM hoặc MariaDB) giữ mở file descriptor trong bộ nhớ — hãy dùng lệnh sudo lsof +L1 để kiểm tra và reload dịch vụ tương ứng. Ngoài ra, cũng có khả năng hệ thống tập tin của bạn đang bật tính năng lưu ảnh chụp tức thời (filesystem snapshots như ZFS/Btrfs/LVM) hoặc đơn giản là bạn vừa xóa file ở một phân vùng khác với phân vùng đang bị đầy.

Có nên tắt hẳn tính năng ghi log của web server và PHP để tiết kiệm dung lượng ổ cứng không?

Đó là cách giải quyết kiểu “đốt nhà diệt chuột”! Nếu file log phình to bất thường, việc đúng đắn cần làm là sửa dứt điểm lỗi trong code đang spam log mỗi giây và cấu hình công cụ xoay vòng nhật ký (logrotate) với chính sách giới hạn dung lượng/thời gian lưu trữ hợp lý. Nếu bạn tắt sạch toàn bộ log, đến lúc website bị tấn công hoặc văng lỗi HTTP 500 thì bạn sẽ hoàn toàn mù tịt không có lấy một dòng manh mối nào để điều tra.

Bước tiếp theo để quản lý dung lượng VPS bền vững

Hãy lập thói quen ghi chép rõ mục tiêu trước mỗi đợt dọn dẹp ổ đĩa, lưu lại bảng số liệu df -hT, df -i và du trước–sau trên cùng một phạm vi và đơn vị đo. Những hạng mục nào chưa trực tiếp kiểm tra thì ghi chú rõ để theo dõi tiếp; nếu kết quả thực tế khác với suy đoán ban đầu, hãy dùng chính số liệu đó để hiểu sâu hơn về cơ chế hoạt động của hệ thống tập tin Linux. Khi đã làm chủ được kỹ năng khoanh vùng và xử lý sự cố đầy đĩa an toàn, mời bạn đi tiếp sang bài học kế tiếp trong series WordPress từ A đến Z.

Tài liệu tham khảo và trạng thái đối chiếu kỹ thuật

Tài liệu đã đối chiếu ngày 01/10/2026: GNU Coreutils: Tài liệu lệnh df, GNU Coreutils: Tài liệu lệnh du, và Ubuntu Noble Manpages: Công cụ lsof(8). Toàn bộ số liệu thực nghiệm và giới hạn của từng phép đo đã được trình bày rõ ở các phần trên; không lấy kết quả của một mẫu thử cô lập để suy diễn cho các kịch bản chưa thực nghiệm.

Tài liệu chuyên sâu bổ sung ngày 01/10/2026: Tài liệu nhân Linux (Kernel v6.12): Cơ chế hệ thống tập tin ảo tmpfs giải thích nguyên lý hoạt động và giới hạn dung lượng trên bộ nhớ ảo; cùng Linux Man-pages: Công cụ unshare(1) và Mount Namespace giải thích cách cô lập không gian gắn kết để thử nghiệm an toàn mà không ảnh hưởng tới hệ thống chính.

Tài liệu WordPress Developer đã đối chiếu ngày 01/10/2026: Hàm wp_handle_sideload() mô tả quy trình kiểm tra và di chuyển tập tin vào thư mục uploads; cùng Hàm wp_insert_post() dùng để tạo và cập nhật bài viết trong cơ sở dữ liệu. Hai hàm API này giúp kiểm chứng tách biệt khả năng ghi file và ghi bản ghi DB từ dòng lệnh, bên cạnh quy trình kiểm tra trên giao diện quản trị.

Tài liệu nền tảng đã đối chiếu ngày 30/09/2026:

Tài liệu tham khảo & Kiểm chứng

CẦN KỸ SƯ HỖ TRỢ TRỰC TIẾP? Đang làm theo hướng dẫn nhưng vướng lỗi hệ thống hoặc sợ đụng chạm dữ liệu đang chạy?

Gửi địa chỉ URL qua Zalo để kỹ thuật viên localhost.vn kiểm tra sơ bộ miễn phí trước khi quyết định can thiệp.

Xem bảng dịch vụ
Góc thực chiến localhost.vn

Mọi hướng dẫn đều dựa trên số liệu đo đạc, log thực tế và nguyên tắc "luôn có đường lùi (Snapshot/Backup) trước khi gõ lệnh".

Nguyên tắc biên tập & Minh bạch ↗