핵심 요약
Too many open files / EMFILE 에러는 프로세스가 열 수 있는 파일 디스크립터(fd) 한계를 초과했다는 뜻이다. 리눅스에서 파일뿐 아니라 소켓·파이프도 모두 fd다. 그래서 동시 접속이 많은 서버가 이 한계에 부딪히면 새 연결을 못 받는다. 해결은 ulimit로 한계를 올리거나, fd 누수를 잡는 것이다.
1. 왜 소켓이 "파일"인가
리눅스는 "모든 것은 파일" 철학이라 열린 파일·TCP 소켓·파이프가 전부 fd로 관리된다. 웹서버가 연결 1만 개를 유지하면 fd도 1만+개다. 기본 한계(흔히 1024)로는 부족하다.
2. 현재 한계·사용량 확인
# 현재 셸의 fd 소프트 한계
ulimit -n
# 특정 프로세스가 연 fd 수
ls /proc/<PID>/fd | wc -l
# 한계 확인
cat /proc/<PID>/limits | grep "open files"
3. 한계 올리기
| 범위 | 방법 |
|---|---|
| 임시(현재 셸) | ulimit -n 65535 |
| 영구(사용자) | /etc/security/limits.conf에 user soft/hard nofile 65535 |
| systemd 서비스 | 유닛에 LimitNOFILE=65535 |
systemd로 뜬 서비스는 limits.conf가 적용되지 않는다 — 반드시 유닛의 LimitNOFILE을 설정해야 한다(자주 놓치는 함정).
4. 진짜 원인이 누수라면
- 파일·소켓·DB 커넥션을 열고 안 닫으면 fd가 계속 쌓인다 — 한계를 올려도 결국 다시 터진다
lsof -p <PID>로 무엇이 쌓이는지 확인. 같은 종류가 계속 늘면 누수- 커넥션 풀을 쓰고,
finally/컨텍스트 매니저로 반드시 닫아라
자주 묻는 질문
ulimit를 올렸는데도 여전히 에러가 나요.
systemd로 실행되는 서비스라면 ulimit/limits.conf가 아니라 유닛의 LimitNOFILE이 적용됩니다. cat /proc/<PID>/limits로 실제 프로세스 한계를 확인하세요. 그리고 셸에서 바꾼 값은 이미 떠 있는 프로세스엔 반영되지 않습니다.
한계를 그냥 아주 크게 잡으면 안 되나요?
65535 정도는 흔하지만, 무작정 키우면 fd 누수를 가릴 뿐입니다. 사용량이 계속 우상향이면 코드에서 소켓·파일·커넥션을 안 닫는 곳을 찾아야 합니다.
소프트 한계와 하드 한계 차이는요?
소프트는 현재 적용값, 하드는 소프트를 올릴 수 있는 상한입니다. 일반 사용자는 하드 한계까지만 소프트를 올릴 수 있고, 하드를 넘기려면 root 설정이 필요합니다.

댓글 0