LabHub
배우기 러닝패스 코스

Linux障害対応

ファイルディスクリプタと上限の診断

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

파일디스크립터의 한도가 몇 겹인지 확인하고, fd 누수를 추적하는 도구를 손으로 만듭니다.

왜 중요한가

Too many open files 를 보면 거의 모두가 ulimit -n 65536 을 실행합니다. 그런데 그 값은 내 셸의 값이고 이미 떠 있는 서비스에는 아무 영향이 없습니다. 확인해야 할 곳은 /proc/<PID>/limits 이고, 실제 사용량은 ls /proc/<PID>/fd | wc -l 입니다(lsof -p 는 cwd·실행파일·mmap 라이브러리까지 세는데 이것들은 한도에 포함되지 않습니다). 그리고 한도를 올리는 것이 답인 경우는 드뭅니다 - 대개 누수이고, 그때 한도 상향은 장애를 몇 시간 뒤로 미루는 일일 뿐입니다. 누수인지 부하인지는 fd 수의 증가 패턴으로 구분합니다.

단계

/root/fd 디렉터리에서 작업합니다.

  1. /proc/1/limits 에서 열린 파일 한도를 읽어 /root/fd/limits.txt 에 다음 두 줄로 적으세요.
    • soft=<값>
    • hard=<값>
  2. /etc/hostname50번 이상 동시에 열고 있는 프로세스를 백그라운드로 띄우고 PID 를 /root/fd/holder_pid.txt 에 적으세요. 이후 단계 내내 살아 있어야 합니다.
  3. 그 프로세스의 fd 중 /etc/hostname 을 가리키는 것의 개수와, 그것들이 가리키는 서로 다른 대상의 개수/root/fd/distinct.txt 에 다음 두 줄로 적으세요.
    • count=<개수>
    • distinct=<개수>
  4. 한도를 낮춘 환경에서 파일을 계속 열어 Too many open files 오류를 재현하고, 그 메시지를 /root/fd/emfile.txt 에 저장하세요.
  5. 시스템 전체 fd 상한을 /root/fd/file_max.txt 에 숫자만 적으세요.
  6. python3 -m http.server 8099 --bind 127.0.0.1 을 백그라운드로 띄우고 PID 를 /root/fd/http_pid.txt 에 적으세요.
  7. /root/fd/fdtop.sh <N> 을 만드세요. 열린 fd 개수 상위 N개 프로세스를 <fd개수> <PID> 형식으로 내림차순 출력합니다. 정확히 N줄이어야 합니다.
  8. /etc/hostname 의 inode 번호를 /root/fd/inode.txt 에 적으세요.

참고

진짜 한도 읽기

/proc/1/limits 에서 열린 파일 한도를 읽어 /root/fd/limits.txt 에 다음 두 줄로 적으세요.

내 셸의 ulimit 이 아니라 그 프로세스의 /proc//limits 를 봐야 합니다. 'Max open files' 줄에 soft 와 hard 가 나란히 있습니다.

fd 50개 붙잡기

/etc/hostname50번 이상 동시에 열고 있는 프로세스를 백그라운드로 띄우고 PID 를 /root/fd/holder_pid.txt 에 적으세요. 이후 단계 내내 살아 있어야 합니다.

python3 로 같은 파일을 여러 번 열어 리스트에 담아 두고 sleep 하면 됩니다. 변수에 담아 두지 않으면 바로 닫힙니다.

fd 개수와 대상 개수 세기

그 프로세스의 fd 중 /etc/hostname 을 가리키는 것의 개수와, 그것들이 가리키는 서로 다른 대상의 개수/root/fd/distinct.txt 에 다음 두 줄로 적으세요.

/proc//fd 의 각 항목을 readlink 해서 대상을 확인하세요. 같은 파일을 여러 번 열면 어떻게 되는지 보세요.

EMFILE 재현하기

한도를 낮춘 환경에서 파일을 계속 열어 Too many open files 오류를 재현하고, 그 메시지를 /root/fd/emfile.txt 에 저장하세요.

서브셸에서 ulimit -n 을 낮추고 그 안에서 파일을 계속 여세요. 오류 메시지를 파일로 저장합니다.

시스템 전체 상한 읽기

시스템 전체 fd 상한을 /root/fd/file_max.txt 에 숫자만 적으세요.

/proc/sys/fs/file-nr 는 숫자 세 개입니다. 마지막이 최대값입니다.

소켓도 fd 다

python3 -m http.server 8099 --bind 127.0.0.1 을 백그라운드로 띄우고 PID 를 /root/fd/http_pid.txt 에 적으세요.

python3 -m http.server 를 127.0.0.1 에 띄우고 그 프로세스의 fd 를 readlink 해 보세요.

fd 상위 프로세스 뽑기

/root/fd/fdtop.sh <N> 을 만드세요. 열린 fd 개수 상위 N개 프로세스를 <fd개수> <PID> 형식으로 내림차순 출력합니다. 정확히 N줄이어야 합니다.

/proc/*/fd 의 항목 수를 세어 정렬합니다. 권한 오류가 나는 항목은 건너뛰세요.

fd 에서 inode 까지 추적

/etc/hostname 의 inode 번호를 /root/fd/inode.txt 에 적으세요.

stat -L 로 심링크를 따라가면 그 fd 가 가리키는 파일의 inode 를 알 수 있습니다.