Too Many Open Files trên Linux: Nguyên nhân và cách xử lý
Lỗi Too Many Open Files khiến ứng dụng Linux không thể mở thêm file, socket hoặc kết nối. Bài viết hướng dẫn kiểm tra giới hạn, tìm tiến trình gây lỗi và xử lý an toàn.
Hướng dẫn thiết lập Nginx FastCGI Cache để giảm số lần PHP phải xử lý yêu cầu, kèm cách loại trừ trang đăng nhập, giỏ hàng và nội dung riêng tư khỏi bộ nhớ đệm.
#Nginx
#FastCGI Cache
#PHP
VVibeVPS
Sẵn sàng triển khai?
Đưa website của bạn lên Cloud VPS ngay hôm nay
Khởi tạo tự động ngay sau khi thanh toán, chuyển khoản bằng mã QR, bật tắt và cài lại máy chủ trong trang quản lý.
Lỗi Too Many Open Files trên Linux thường xuất hiện khi một tiến trình đã dùng hết số file descriptor được phép mở. Khi đó, ứng dụng có thể không đọc được file, tạo kết nối mới hoặc tiếp tục phục vụ yêu cầu. Dù thông báo nhắc đến “file”, tài nguyên bị tính giới hạn còn bao gồm socket mạng, pipe và một số thiết bị.
Để xử lý lỗi giới hạn file Linux hiệu quả, bạn cần xác định giới hạn nào đã chạm ngưỡng, tìm tiến trình liên quan rồi chọn giải pháp phù hợp. Chỉ tăng giới hạn mà không kiểm tra nguyên nhân có thể khiến lỗi tái diễn hoặc che giấu tình trạng rò rỉ tài nguyên.
Vì sao Linux báo Too Many Open Files?
Mỗi tiến trình Linux có thể mở một số lượng file descriptor nhất định. File descriptor là mã định danh mà tiến trình sử dụng để truy cập tài nguyên như file, socket và pipe. Hệ điều hành áp dụng giới hạn cho từng tiến trình, đồng thời có giới hạn tổng ở cấp hệ thống.
Hai tình huống thường gặp là:
EMFILE: một tiến trình đã đạt giới hạn file descriptor riêng.
ENFILE: hệ thống đã cạn số file handle có thể cấp phát trên toàn máy.
Nguyên nhân phổ biến gồm ứng dụng không đóng file hoặc kết nối sau khi sử dụng, lượng kết nối đồng thời tăng cao, cấu hình worker hoặc connection pool chưa phù hợp, hay giới hạn của dịch vụ thấp hơn nhu cầu thực tế. Một tiến trình có thể giữ nhiều socket hơn dự kiến nếu kết nối bị treo hoặc không được thu hồi đúng cách.
Cần phân biệt lỗi này với tình trạng cạn inode hoặc đầy dung lượng đĩa. Đây là các vấn đề riêng, dù đôi khi cùng xuất hiện trên một máy chủ.
Kiểm tra giới hạn file đang mở
Quản trị viên kiểm tra giới hạn file mở trên máy chủ Linux
Bước đầu tiên là kiểm tra giới hạn áp dụng trong phiên shell hiện tại:
ulimit -n
ulimit -Sn
ulimit -Hn
ulimit -Sn hiển thị giới hạn mềm (soft limit), tức ngưỡng tiến trình thường chịu khi chạy. ulimit -Hn là giới hạn cứng (hard limit), mức tối đa mà người dùng có thể nâng soft limit nếu được phép. Lệnh ulimit -n thường hiển thị soft limit của shell hiện tại.
Lưu ý, kết quả trong terminal không nhất thiết là giới hạn của ứng dụng chạy nền. Dịch vụ khởi động bằng systemd có thể nhận cấu hình riêng. Hãy tìm PID của ứng dụng, sau đó kiểm tra giới hạn thực tế:
cat /proc/<PID>/limits | grep -i "open files"
Thay <PID> bằng mã tiến trình cần kiểm tra. Bạn cũng có thể xem dịch vụ systemd đang áp dụng giới hạn nào:
systemctl show ten-dich-vu -p LimitNOFILE
Để kiểm tra giới hạn file handle ở cấp hệ thống, dùng:
file-nr thường trả về ba giá trị: số file handle đã cấp phát, số handle đã cấp phát nhưng chưa dùng và ngưỡng tối đa của hệ thống. Cách diễn giải chi tiết có thể khác đôi chút tùy phiên bản kernel. Nếu mức sử dụng tiến sát ngưỡng trong khi nhiều dịch vụ cùng gặp lỗi, cần xem xét tình trạng toàn máy thay vì chỉ điều chỉnh một ứng dụng.
Tìm tiến trình gây lỗi
Tìm tiến trình Linux đang sử dụng nhiều file descriptor
Khi đã có PID, đếm số descriptor tiến trình đang giữ:
ls /proc/<PID>/fd | wc -l
Đây là số lượng tại thời điểm kiểm tra; hoạt động của ứng dụng có thể khiến con số thay đổi liên tục. Để xem các file và socket cụ thể, nếu máy đã cài lsof, chạy:
sudo lsof -nP -p <PID>
Muốn đếm số mục lsof ghi nhận cho tiến trình:
sudo lsof -nP -p <PID> | wc -l
Kết quả có thể tính cả dòng tiêu đề, vì vậy hãy dùng nó để quan sát xu hướng hơn là coi đó là số tuyệt đối chính xác. Tùy quyền truy cập và trạng thái tiến trình, một số thông tin cũng có thể không hiển thị.
Nếu chưa biết PID, liệt kê tiến trình đang mở nhiều file descriptor:
sudo lsof -nP | awk 'NR > 1 {count[$2]++} END {for (pid in count) print count[pid], pid}' | sort -nr | head
Lệnh trên giúp xác định các PID cần kiểm tra thêm; không thể kết luận tiến trình nào có lỗi chỉ dựa vào số lượng lớn. Hãy đối chiếu PID với tên dịch vụ bằng ps -fp <PID> hoặc kiểm tra trạng thái systemd:
systemctl status ten-dich-vu
journalctl -u ten-dich-vu --since "30 minutes ago"
Tìm thông báo lỗi, thời điểm bắt đầu tăng tải và loại descriptor tăng bất thường. Nhiều file cùng trỏ đến cùng một log có thể là hành vi bình thường; số lượng socket tăng mãi, không giảm sau khi tải hạ, lại là dấu hiệu đáng điều tra.
Cách sửa Too Many Open Files
Điều chỉnh cấu hình dịch vụ để xử lý lỗi Too Many Open Files
Chọn cách sửa dựa trên phạm vi giới hạn và nguyên nhân đã xác định. Trước khi thay đổi, ghi lại cấu hình hiện tại và chỉ áp dụng mức tăng có căn cứ.
1. Tăng giới hạn cho dịch vụ systemd
Với dịch vụ chạy bằng systemd, tạo hoặc chỉnh cấu hình override thay vì sửa trực tiếp unit gốc:
sudo systemctl edit ten-dich-vu
Thêm nội dung, trong đó N là giá trị phù hợp với nhu cầu đã đo được:
[Service]
LimitNOFILE=N
Sau đó tải lại cấu hình và khởi động lại dịch vụ để giới hạn mới có hiệu lực:
Xác nhận bằng systemctl show ten-dich-vu -p LimitNOFILE và /proc/<PID>/limits. Việc chỉ chạy ulimit -n N trong terminal thường không thay đổi giới hạn của một dịch vụ đã được systemd khởi chạy.
2. Điều chỉnh giới hạn trong phiên shell hoặc cấu hình người dùng
Để thử nghiệm trong shell hiện tại, có thể dùng:
ulimit -n N
Thay đổi này chỉ ảnh hưởng đến shell và các tiến trình con được khởi chạy từ đó; nó không tự động tồn tại sau khi đăng xuất. Cấu hình giới hạn đăng nhập lâu dài có thể được quản lý qua /etc/security/limits.conf hoặc các tệp trong /etc/security/limits.d/. Tuy nhiên, cách này chỉ có hiệu lực khi đường đăng nhập sử dụng PAM và không thay thế cấu hình LimitNOFILE của systemd.
3. Xử lý giới hạn cấp hệ thống
Nếu file-nr cho thấy toàn máy tiến sát file-max, hãy rà soát các tiến trình đang mở nhiều descriptor và xác định tải phát sinh từ đâu. Tham số fs.file-max là giới hạn toàn hệ thống; chỉ cân nhắc điều chỉnh khi đã hiểu nhu cầu bộ nhớ và tác động của máy chủ. Các giá trị fs.nr_open và giới hạn theo tiến trình cũng có thể liên quan, nên không nên tăng riêng một tham số rồi mặc định rằng mọi tiến trình đã được nới giới hạn.
Khi thử thay đổi tạm thời, dùng sysctl và kiểm tra kết quả. Nếu cần duy trì sau khi khởi động lại, cấu hình theo cơ chế quản lý sysctl của hệ điều hành. Thực hiện từng thay đổi, theo dõi lại file-nr, log và mức sử dụng của dịch vụ.
4. Khắc phục nguyên nhân trong ứng dụng
Tăng giới hạn không thay thế việc sửa lỗi rò rỉ tài nguyên. Hãy kiểm tra ứng dụng có đóng file sau khi đọc, giải phóng socket khi kết nối kết thúc và xử lý lỗi khi mở tài nguyên mới hay không. Với dịch vụ mạng, rà soát connection pool, số worker, thời gian chờ và cách thu hồi kết nối. Đóng các file descriptor cũ đúng cách, rồi triển khai bản sửa theo quy trình an toàn.
Không nên tùy tiện kết thúc tiến trình bằng kill -9: thao tác này có thể làm gián đoạn dịch vụ hoặc gây mất dữ liệu chưa ghi. Nếu phải khởi động lại để khôi phục tạm thời, hãy thực hiện có kế hoạch và tiếp tục tìm nguyên nhân gốc.
5. Kiểm tra lại sau khi xử lý
Sau khi thay cấu hình hoặc triển khai bản sửa, xác nhận giới hạn mới trên chính PID của dịch vụ. Theo dõi số descriptor trong /proc/<PID>/fd, log ứng dụng và /proc/sys/fs/file-nr khi tải tăng. Nếu chỉ một tiến trình chạm giới hạn, tập trung vào dịch vụ đó; nếu nhiều dịch vụ cùng lỗi, điều tra giới hạn toàn hệ thống và nhu cầu tài nguyên tổng thể.
Một số ứng dụng còn có giới hạn tài nguyên riêng, chẳng hạn giới hạn số lượng watcher của inotify. Đây không phải lúc nào cũng là lỗi Too Many Open Files, vì vậy hãy đọc chính xác thông báo lỗi trước khi thay đổi sysctl.
Cách hạn chế lỗi tái diễn
Đưa việc đóng file, socket và giải phóng tài nguyên vào quy trình kiểm thử ứng dụng.
Theo dõi số descriptor theo thời gian, thay vì chỉ kiểm tra lúc dịch vụ đã lỗi.
Đặt giới hạn phù hợp với tải dự kiến và cấu hình worker, tránh tăng tùy tiện lên mức rất cao.
Ghi lại cấu hình systemd, sysctl và thay đổi liên quan để dễ kiểm tra khi sự cố lặp lại.
Kiểm tra log sau khi triển khai hoặc thay đổi lưu lượng, đặc biệt khi số kết nối đồng thời tăng.
Tổng kết
Để sửa Too Many Open Files Linux, hãy phân biệt lỗi giới hạn của một tiến trình với giới hạn toàn hệ thống, kiểm tra giới hạn thực tế của dịch vụ và dùng lsof hoặc /proc/<PID>/fd để tìm nguyên nhân. Sau đó mới điều chỉnh cấu hình hoặc sửa cách ứng dụng quản lý file descriptor. Nếu đang cần môi trường máy chủ để vận hành dịch vụ Linux, bạn có thể tham khảo các gói VPS AMD EPYC Gen 3 của VibeVPS từ 81.000đ/tháng và lựa chọn cấu hình phù hợp với nhu cầu.
Hướng dẫn cài GitLab trên VPS từ khâu chuẩn bị máy chủ, trỏ tên miền đến thiết lập bảo mật và sao lưu. Phù hợp với cá nhân, nhóm phát triển muốn tự quản lý kho mã nguồn.