배경
파이썬 프로세스가 런타임에서 제목과 같은 에러로 종료되는 경우가 있다. 하나의 프로세스가 열고 있는 파일의 수가 Max open files 제한을 초과한 경우 발생한다.
해결방법
- 현재 터미널 세션의 limit 확인
- 프로세스 실행 후 open files 수 확인
- 현재 터미널 세션의 limit 설정수정
1. 현재 터미널 세션의 limit 확인
터미널에서 프로세스를 실행하게 되면 해당 터미널을 부모로 갖는 프로세스가 생성되게 된다. 따라서 터미널 세션의 로컬 설정을 따르게 되는데 이때 로컬의 설정을 아래 명령어로 확인한다.
# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 256616
max locked memory (kbytes, -l) 16384
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 256616
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
open files 의 max가 1024임으로 해당 터미널에서 실행된 프로세스들은 1024이상의 파일을 열시 OSError: [Errno 24] Too many open files 로 종료된다.
해당 프로세스의 실제 limit을 확인하는 방법도 있다. 두개의 결과가 상이할 수 있기때문에 아래의 명령어로 확인하는것이 더 신뢰할수 있다.
# cat /proc/{pid}/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 256616 256616 processes
Max open files 1024 1048576 files
Max locked memory 16777216 16777216 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 256616 256616 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
2. 프로세스의 실행 후 open files 수 확인
실제로 프로세스가 몇개의 파일을 열고 있는지 확인하면서 문제원인을 확인해야한다.
# sudo lsof -p {pid} | wc -l
{열고 있는 파일 수}
sudo는 일부파일의 권한 문제로 인해 참조하지 못하는 파일이 있을시 정확한 파일수를 얻을수 없기때문이다. 문제의 프로세스 실행후에 실시간으로 해당 명령어를 입력하여 확인한다. 계속 증가하며 max에 도달하여 죽을시 파일 읽는 코드에 leak문제가 있을 수 있다. (보통 open() 하고 close() 하지 않은 file descriptor들)
3. 현재 터미널 세션의 limit 설정수정
계속해서 증가 하진않지만 어느순간 죽는다면 local이나 global의 max limit을 수정해주는것으로 해결될 수 있다.
# ulimit -n 10000
위 방법은 로컬 세션에 대한 설정이기 때문에 해당 세션에만 적용됨으로 글로벌하게 적용할시에는 아래의 파일을 추가 혹은 수정하면된다.
# vim /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535
마치며
위 문제를 해결할때 문제원인을 파악하지 않고 단순히 설정을 수정하는것은 오히려 시스템에 좋지 않을 수 있다. 데이터로더에서 파일을 닫지않고 참조할때마다 여는 경우와 같이 코드문제라면 설정을 바꾸기 이전에 디버깅을 하는것을 추천한다. 또한, 우선 로컬의 설정을 바꾸고 동작여부를 확인후 글로벌 설정을 바꾸는 것을 권장한다.
위 포스트는 개인적인 경험에 의한 작성이며 문제나 틀린부분이 있으면 댓글로 알려주시면 감사하겠습니다.