Too many open files. 트래픽이 늘거나 커넥션이 쌓이는 서버에서 흔히 만나는 에러입니다. 리눅스는 프로세스마다 동시에 열 수 있는 파일 디스크립터(FD) 수에 한도를 두는데, 소켓·파이프·로그 파일이 모두 FD를 잡아먹기 때문에 생각보다 빨리 차오릅니다. 한도를 무작정 올리기 전에, 한도가 진짜 문제인지부터 가립니다.
1단계 — 지금 한도가 얼마인가 (ulimit)
먼저 현재 셸·프로세스의 한도를 봅니다.
로컬 터미널
ulimit -n # soft limit (현재 적용값)
ulimit -Hn # hard limit (올릴 수 있는 상한)
문제를 일으키는 프로세스의 실제 한도는 /proc에서 직접 확인하는 게 정확합니다.
로컬 터미널
cat /proc/<PID>/limits | grep "open files"
2단계 — 누가 FD를 다 쓰고 있나 (lsof)
한도가 낮은 게 아니라, FD가 새고 있는(누수) 경우도 많습니다. 프로세스별로 몇 개를 열고 있는지 셉니다.
로컬 터미널
lsof -p <PID> | wc -l # 특정 프로세스의 열린 FD 수
ls /proc/<PID>/fd | wc -l # 더 가벼운 방법
전체에서 FD를 많이 쓰는 프로세스를 찾으려면 정렬합니다.
로컬 터미널
lsof | awk '{print $2}' | sort | uniq -c | sort -rn | head
같은 소켓·파일이 끝없이 늘어난다면 한도가 아니라 애플리케이션 누수입니다. 이 경우 한도를 올려도 시간만 벌 뿐, 코드를 고쳐야 합니다.
3단계 — 한도 올리기
누수가 아니라 정당한 부하라면 한도를 올립니다. 적용 범위에 따라 방법이 다릅니다.
| 범위 | 방법 | 비고 |
|---|---|---|
| 현재 셸만 (임시) | ulimit -n 65536 | hard limit 이내에서만 |
| 사용자 영구 | /etc/security/limits.conf | 재로그인 필요 |
| systemd 서비스 | 유닛의 LimitNOFILE= | ulimit·limits.conf 무시함 |
limits.conf에는 soft·hard를 함께 적습니다.
로컬 터미널
# /etc/security/limits.conf
appuser soft nofile 65536
appuser hard nofile 65536
데몬이 systemd로 뜬다면 limits.conf는 적용되지 않습니다. 유닛에 직접 박아야 합니다.
로컬 터미널
# /etc/systemd/system/myapp.service.d/override.conf
[Service]
LimitNOFILE=65536
이후 sudo systemctl daemon-reload && sudo systemctl restart myapp 으로 반영합니다.
점검 체크리스트
로컬 터미널
ulimit -n # 현재 soft limit
cat /proc/<PID>/limits | grep "open files" # 프로세스 실제 한도
ls /proc/<PID>/fd | wc -l # 실제 사용 중인 FD 수
# 한도 < 사용량 → 상향, 사용량이 계속 증가 → 누수 의심
FD 한도와 ulimit·systemd 리소스 제어를 직접 만져보는 실습은 리눅스 트랙에서 회원가입 없이 무료로 익힐 수 있습니다.