Hệ điều hành · 18/10/2026

Linux Too many open files: chẩn đoán đúng trước khi tăng giới hạn

Ứng dụng không mở được kết nối mới dù CPU và RAM vẫn còn dư. Log xuất hiện “Too many open files”, nhưng tăng một con số trong terminal không làm service hết lỗi. Cần xác định đúng tiến trình, loại tài nguyên và tầng giới hạn trước khi thay đổi.

Linux Too many open files: chẩn đoán đúng trước khi tăng giới hạn

Ứng dụng không mở được kết nối mới dù CPU và RAM vẫn còn dư. Log xuất hiện “Too many open files”, nhưng tăng một con số trong terminal không làm service hết lỗi. Cần xác định đúng tiến trình, loại tài nguyên và tầng giới hạn trước khi thay đổi.

Bài viết đưa ra quy trình điều tra trên Linux dùng procfs và systemd. app.service cùng PID 1234 là ví dụ cần thay thế. Các lệnh chẩn đoán là thao tác đọc; bài viết không thực hiện thay đổi cấu hình hoặc restart service production.

1. “File” ở đây còn có socket và pipe

File descriptor là định danh mà tiến trình dùng để làm việc với tài nguyên I/O. Nó có thể trỏ tới file thường, socket, pipe hoặc một đối tượng kernel khác. Vì vậy, lỗi này có thể biểu hiện ở accept kết nối, mở log hoặc gọi dịch vụ bên ngoài.

Tài liệu proc_pid_fd mô tả các mục trong /proc/PID/fd. Danh sách đó là điểm bắt đầu để biết tiến trình đang giữ loại descriptor nào, không chỉ bao nhiêu file trên đĩa.

2. Phân biệt EMFILE với ENFILE

Tín hiệuPhạm vi cần điều traHành động đầu tiên
EMFILEGiới hạn descriptor của tiến trìnhXác định PID lỗi, số descriptor và RLIMIT_NOFILE
ENFILEGiới hạn file handle ở cấp hệ thốngĐối chiếu tình trạng toàn host và các workload

getrlimit(2) giải thích RLIMIT_NOFILE và soft/hard limit. Soft limit là mức được thực thi; hard limit đặt trần cho việc điều chỉnh soft trong điều kiện quyền thông thường.

Đừng chỉ nhìn chuỗi lỗi đã được thư viện dịch lại. Nếu có thể, giữ errno, syscall, timestamp và PID để biết ứng dụng vướng tầng nào. Một host có nhiều worker cần xem từng tiến trình liên quan, không chỉ tổng số của service.

3. Đọc giới hạn của tiến trình đang chạy

systemctl show app.service -p MainPID -p LimitNOFILE -p LimitNOFILESoft
cat /proc/1234/limits
ls -l /proc/1234/fd

Xác minh PID còn thuộc đúng workload trước khi đọc, vì tiến trình có thể đã restart. MainPID cũng không bảo đảm là worker phát sinh lỗi; ứng dụng có thể có master và nhiều child process. Nếu không được phép đọc procfs của PID, ghi nhận lỗi quyền thay vì coi output rỗng là “không có descriptor”.

Đường dẫn và socket trong danh sách có thể tiết lộ thông tin nội bộ. Khi chia sẻ kết quả điều tra, chỉ trích phần cần thiết và che dữ liệu nhạy cảm.

ulimit -Sn
ulimit -Hn

Hai lệnh trên trong Bash chỉ cho biết giới hạn của shell hiện tại. Chúng hữu ích khi điều tra tiến trình được shell đó khởi chạy, nhưng không chứng minh giới hạn của service do systemd hoặc container runtime quản lý.

4. Quan sát xu hướng thay vì kết luận từ một ảnh chụp

Lấy các mẫu cùng PID, cùng thời điểm với traffic và số job đang xử lý. Một pool kết nối tăng rồi ổn định có thể khác hoàn toàn một lượng descriptor tăng mãi sau mỗi vòng công việc.

  • Phân loại file thường, socket và pipe trong các mẫu.
  • Đối chiếu với concurrency, retry, timeout và connection pool.
  • Kiểm tra các nhánh exception có đóng tài nguyên không.
  • Quan sát sau khi tải giảm: descriptor có trở về mức nền phù hợp không?
  • Ghi riêng sự kiện deploy hoặc restart để không đọc nhầm đường biểu diễn bị reset.

Ví dụ số socket tăng theo số request đang bay có thể chỉ ra pool hoặc concurrency chưa được giới hạn. File log mở lặp mà không đóng gợi ý một nhánh code khác. Đây là giả thuyết để kiểm tra, không phải kết luận chỉ từ tên tài nguyên.

5. Chỉ nhìn giới hạn toàn host khi có bằng chứng phù hợp

cat /proc/sys/fs/file-nr
cat /proc/sys/fs/file-max
cat /proc/sys/fs/nr_open

Tài liệu sysctl fs của Linux kernel phân biệt file-max ở cấp hệ thống với nr_open, trần kernel liên quan số descriptor cho một tiến trình. file-nr không phải tổng số thư mục hoặc file đang lưu trên ổ đĩa.

Các số ở những tầng này không nên được cộng, trừ hoặc so sánh như cùng một loại bộ đếm. Nếu lỗi nằm ở soft limit của một worker, tăng file-max không tự thay đổi soft limit đó. Ngược lại, xử lý một PID đơn lẻ có thể chưa đủ khi toàn host thật sự bị áp lực file handle.

6. Nếu cần tăng LimitNOFILE, thay đổi có mục tiêu

systemd.exec tài liệu hóa LimitNOFILE cho môi trường service. Cấu hình phải đặt ở đúng unit/launcher và được kiểm tra lại trên PID thực tế sau khi áp dụng.

Trước khi tăng, xác định ứng dụng có hỗ trợ descriptor số lớn không. Chương trình còn dùng select có giới hạn cần lưu ý; không mặc định nâng soft limit lên rất cao là an toàn cho mọi runtime.

Chọn giá trị từ số kết nối dự kiến, tài nguyên phụ trợ và headroom có lý do. Review ảnh hưởng tới bộ nhớ, upstream và số worker. Diễn tập thay đổi trong môi trường kiểm thử, có kế hoạch restart/rolling rollout cùng rollback; không thao tác restart mọi service chỉ để “nhận limit mới”.

Tăng giới hạn có thể là biện pháp khôi phục năng lực hợp lệ, nhưng cũng có thể chỉ kéo dài thời gian trước khi rò rỉ lặp lại. Theo dõi xu hướng sau thay đổi và sửa vòng đời tài nguyên trong ứng dụng nếu nguyên nhân là leak.

7. Checklist kết thúc sự cố

  1. Đã ghi đúng PID, errno và đường khởi chạy workload.
  2. Đã đọc giới hạn runtime thay vì suy ra từ terminal.
  3. Có nhiều mẫu cho thấy loại descriptor và tốc độ tăng.
  4. Biện pháp xử lý khớp tầng giới hạn được chứng minh.
  5. Đã xác minh soft/hard limit của tiến trình mới nếu có rollout.
  6. Traffic thật hoạt động, lỗi giảm và descriptor không tăng bất thường trở lại.
  7. Có cảnh báo dựa trên headroom và xu hướng, cùng người chịu trách nhiệm xử lý nguyên nhân.

Chẩn đoán Too many open files bắt đầu từ tài nguyên tiến trình đang giữ. Đọc đúng tầng và quan sát theo thời gian giúp phân biệt thiếu năng lực hợp lệ với rò rỉ cần sửa, thay vì chỉ chuyển sự cố sang một ngưỡng cao hơn.

Thảo luận

Bình luận 0

Đăng nhập để bình luận

Bạn cần có tài khoản để tham gia thảo luận và trả lời độc giả khác.

Đăng nhậpĐăng ký

Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.