[server] 루트에서 사용중인 열린 파일 디스크립터 수가 ulimit -n을 초과하는 이유는 무엇입니까?

최근 서버에 파일 설명자가 부족하여 질문이 있습니다. ulimit -n열린 파일 디스크립터의 최대 수를 알려줍니다. 그 숫자는 1024입니다. 실행 lsof -u root |wc -l하여 열린 파일 설명자 수를 확인하고 2500 fds를 얻었습니다. 그것은 1024보다 훨씬 큽니다. 그래서 1024는 사용자가 아닌 프로세스 당 수를 의미한다고 생각했습니다. 글쎄, 나는 달리고 lsof -p$PidOfGlassfish|wc -l1300을 얻었다. 이것은 내가 얻지 못하는 부분이다. ulimit -n사용자 당 또는 프로세스 당 최대 프로세스 수가 아닌 경우 어떤 이점이 있습니까? 루트 사용자에게는 적용되지 않습니까? 그렇다면 어떻게 파일 설명자 부족에 대한 오류 메시지를 얻을 수 있습니까?

편집 : 내가 이해할 수있는 유일한 방법 ulimit -n은 파일 핸들 수가 아닌 열려있는 파일 수 (bash 매뉴얼에 명시된 바와 같이)를 적용하는 것입니다 (다른 프로세스는 동일한 파일을 열 수 있습니다). 이 경우에는 열려있는 파일 수를 나열하는 것만으로도 충분 하지 않습니다 ( ‘/’를 그리 면서 메모리 매핑 된 파일 제외) .

lsof -u root |grep /|sort  -k9  |wc -l #prints '1738'

실제로 열린 파일 수를 보려면 고유 항목 만 인쇄 할 때 이름 열을 필터링해야합니다. 따라서 다음이 더 정확할 것입니다.

lsof -u root |grep /|sort  -k9 -u |wc -l #prints '604'

위 명령은 lsof에서 다음 형식의 출력을 예상합니다.

java      32008 root  mem       REG                8,2 11942368      72721 /usr/lib64/locale/locale-archive
vmtoolsd   4764 root  mem       REG                8,2    18624     106432 /usr/lib64/open-vm-tools/plugins/vmsvc/libguestInfo.so

이것은 적어도 1024 미만의 숫자 ((에 의해보고 된 숫자 ulimit -n)를 제공하므로 올바른 방향의 단계처럼 보입니다. “안타깝게도”파일 디스크립터 부족 문제가 발생하지 않으므로이를 확인하는 데 어려움이 있습니다.



답변

나는 이것을 Linux 버전 2.6.18-164.el5-Red Hat 4.1.2-46에서 테스트했다. 프로세스 당 ulimit가 적용되는 것을 볼 수 있습니다.

매개 변수는 사용자 레벨에서 설정되지만 각 프로세스에 적용됩니다.

예 : 1024가 한계였습니다. 여러 프로세스가 시작되었고 각 프로세스에서 열린 파일은

ls -l /proc/--$pid--/fd/ | wc -l

여러 프로세스에서 열린 파일의 합계가 1024를 넘을 때 오류가 없었습니다. 또한 다른 프로세스의 결과와 고유 파일 수를 결합하여 고유 파일 수를 확인했습니다. 각 프로세스의 수가 1024를 초과 할 때만 오류가 표시되기 시작했습니다 (java.net.SocketException : 프로세스 로그에 열린 파일이 너무 많습니다)


답변

ulimit는 파일 핸들 용입니다. 파일, 디렉토리, 소켓, 파이프 epoll, eventfd, timerfds 등에 적용됩니다.

프로세스 시작 중 언제든지 제한이 변경되었을 수 있습니다. 방문 /proc/<pid>/limits하여 값이 변경되었는지 확인하십시오.


답변

@oligofren

나는 또한 방법을 결정하는 몇 가지 테스트 수행 "ulimits -Sn"을 위해이 "open files"시행되었다.

  • 포스터처럼 선택된가 에 언급 된 링크 에 대한 ulimit를이 "open files"참으로 프로세스 당 적용됩니다. 프로세스의 현재 한계가 무엇인지 확인하려면 다음을 수행하십시오.

    cat /proc/__process_id__/limits

  • 프로세스가 얼마나 많은 파일을 열 었는지 확인하려면 다음 명령을 사용해야합니다.

    lsof -P -M -l -n -d '^cwd,^err,^ltx,^mem,^mmap,^pd,^rtd,^txt' -p __process_id__ -a | awk '{if (NR>1) print}' | wc -l

위의 설명 및 테스트 방법 / 결과

"-P -M -l -n"인수 lsof를가 하도록 단순히있다 lsof를가 할 수있는 한 가장 빠른 속도로 작동합니다. 자유롭게 꺼내십시오.

-P - inhibits the conversion of port numbers to port names for network files
-M - disable reporting of portmapper registrations for local TCP, UDP and UDPLITE ports
-l - inhibits the conversion of user ID numbers to login names
-n - inhibits the conversion of network numbers to host names for network files

"-d '^cwd,^err,^ltx,^mem,^mmap,^pd,^rtd,^txt'"인수는 lsofcwd / err / ltx / mem / mmap / pd / rtd / txt 유형의 파일 디스크립터를 제외 하도록 지시 합니다.

lsof 매뉴얼 페이지에서 :

   FD         is the File Descriptor number of the file or:

                   cwd  current working directory;
                   Lnn  library references (AIX);
                   err  FD information error (see NAME column);
                   jld  jail directory (FreeBSD);
                   ltx  shared library text (code and data);
                   Mxx  hex memory-mapped type number xx.
                   m86  DOS Merge mapped file;
                   mem  memory-mapped file;
                   mmap memory-mapped device;
                   pd   parent directory;
                   rtd  root directory;
                   tr   kernel trace file (OpenBSD);
                   txt  program text (code and data);
                   v86  VP/ix mapped file;

"Lnn,jld,m86,tr,v86"Linux에는 해당되지 않는 것으로 간주 되어 제외 목록에 추가하지 않았습니다. 확실하지 않습니다 "Mxx".

응용 프로그램 차종은 메모리 매핑 된 파일의 사용하는 경우 / 디바이스 당신은 제거 할 수 있습니다 "^mem""^mmap"제외 목록에서.

편집 — 저격 시작 —

편집 : 나는 그것을 나타내는 다음 링크 를 발견 했다.

메모리 매핑 된 .so 파일은 기술적으로 응용 프로그램이 제어하는 ​​파일 핸들과 다릅니다. / proc // fd는 열린 파일 디스크립터의 측정 지점입니다.

따라서 프로세스에서 메모리 매핑 된 파일을 사용하는 경우 * .so 파일을 필터링해야합니다.

또한 Sun의 JVM은 jar 파일을 메모리 맵에 저장합니다

메모리 맵핑 JAR 파일 (이 경우 “JDK 클래스”를 보유하는 파일) JAR을 메모리 맵핑 할 때, 매번 처음부터 파일을 읽는 것과는 달리 JAR 파일 내의 파일에 매우 효율적으로 액세스 할 수 있습니다. Sun JVM은 클래스 경로의 모든 JAR을 메모리 매핑합니다. 애플리케이션 코드가 JAR에 액세스해야하는 경우 메모리 맵핑 할 수도 있습니다.

따라서 tomcat / glassfish와 같은 것들도 메모리 매핑 jar 파일을 보여줍니다. 나는 이것들이 한계에 해당하는지 테스트하지 않았다"ulimit -Sn" .

편집 — 끝 싹둑 —

경험적으로, 나는 것으로 나타났습니다 "cwd,rtd,txt"되어 계산되지 프로세스 당 파일 제한에 관해서 (ulimit를 -Sn)와 함께.

"err,ltx,pd"이러한 디스크립터 유형의 파일 핸들을 작성하는 방법을 모르므로 파일 제한에 포함 되는지 확실 하지 않습니다.

"-p __process_id__"인수 제한합니다은 lsof단지에 대한 정보를 반환 __process_id__지정합니다. 모든 프로세스 수를 얻으려면 이것을 제거하십시오.

"-a"인수하는 데 사용됩니다 선택 사항 (즉, “-p”와 “-d”인수).

"awk '{if (NR>1) print}'"명령문은 lsof출력으로 인쇄 되는 헤더를 건너 뛰는 데 사용됩니다 .

다음 perl 스크립트를 사용하여 테스트했습니다.

File: test.pl
---snip---
#!/usr/bin/perl -w
foreach $i (1..1100) {
  $FH="FH${i}";
  open ($FH,'>',"/tmp/Test${i}.log") || die "$!";
  print $FH "$i\n";
}
---snip---

스크립트가 파일 디스크립터를 종료하고 해제하지 않도록 perl 디버거에서 스크립트를 실행해야했습니다.

실행하다: perl -d test.pl

perl의 디버거에서 center 를 입력 하고 눌러 프로그램을 실행할 수 ulimit -Sn있으며 값이 1024 인 경우에 Test1017.log파일을 작성한 후 프로그램이 중지 됩니다 /tmp.

이제 perl 프로세스의 pid를 식별하고 위의 lsof명령을 사용하면 1024 도 출력 함을 알 수 있습니다 .

1024 제한에 포함 된 파일 목록을 보려면를 제거하고 "wc -l"a "less"로 바꾸 십시오 . 및 설명자가 한계에 포함 되지 않았는지 확인 하려면 인수를 제거하십시오 ."-d ^....."cwd,txtrtd

이제를 실행 "ls -l /proc/__process_id__/fd/ | wc -l"하면 1025 값이 반환됩니다. 계산에 출력에 헤더를 ls추가 했기 때문 "total 0"입니다.

노트 :

OS에 파일 디스크립터가 부족한지 확인하려면 다음 값 을 비교 하는 것이 좋습니다 .

cat /proc/sys/fs/file-nr | awk '{print $1}'

cat /proc/sys/fs/file-max

https://www.kernel.org/doc/Documentation/sysctl/fs.txt는 무엇 file-nrfile-max의미 하는지 문서화합니다 .


답변

당신의 추론은 “귀한 설명자가 부족하지 않도록 한계를 낮춰야합니다”와 같은 것 같습니다. 진실은 정확히 반대입니다 – 서버가 파일 기술자가 부족하면, 당신은 할 필요가 인상 더 큰 무언가에 1,024에서 그 한계를. 현실적인 glassfish구현을 위해서는 32,768이 합리적입니다.

개인적으로 저는 항상 시스템 전체에서 약 8,192 개로 제한을 올립니다. 1,024는 말도 안됩니다. 하지만 glassfish더 높이고 싶을 것 입니다. 확인하십시오 /etc/security/limits.conf. 사용자 glassfish가 다음과 같이 실행할 수 있도록 특수 항목을 추가 할 수 있습니다 .


답변

/ proc / sys / fs / file-max에 설정된 시스템 전체의 한계를보고 그 값을 조정 (다음 재부팅 할 때까지)하거나 sysctl.conf에서 fs.file-max를 설정하여 영구적으로 만들려고합니다. 도움이 될 수 있습니다-http: //www.randombugs.com/linux/tuning-file-descriptors-limits-on-linux.html


답변

원시 lsof 호출의 결과를 가정 된 한계와 비교하는 일반적인 실수입니다.

전역 제한 (/ proc / sys / fs / file-max)의 경우 / proc / sys / fs / file-nr을 확인해야합니다.-> 첫 번째 값은 사용 된 값을 나타내며 마지막 값은 제한입니다

OpenFile 제한은 각 프로세스에 대한 것이지만 사용자에 대해 정의 될 수 있습니다. 사용자 제한에 대해서는 “ulimit -Hn”명령을 참조하고 정의에 대해서는 /etc/security/limits.conf를 참조하십시오. 일반적으로 “app user”와 함께 적용됩니다. 예 : “tomcat”: Java 프로세스에서 실행될 tomcat에 한계를 65000으로 설정하십시오.

프로세스에 적용된 한계를 확인하려면 해당 PID를 가져온 다음 cat / proc / $ {PID} / limits 프로세스를 통해 열린 파일 수를 확인하려면 PID를 가져온 후 다음을 수행하십시오. ls -1 / proc / {PID} / fd | wc -l (ls의 경우 ‘빼기 1’, ‘빼기 el’와 일치하지 않음)

lsof로 세부 사항을 알고 싶지만 한계를 계산하는 파일 전달자에 대해서만 알고 싶다면 lsof -p $ {PID} | grep -P “^ (\ w + \ s +) {3} \ d + \ D +”lsof -p $ {PID} -d ‘^ cwd, ^ err, ^ ltx, ^ mem, ^ mmap, ^ pd, ^ rtd, ^ txt ‘-a

비고 : ‘파일’은 파일 / 파이프 / TCP 연결 등입니다.

때때로 당신은 아마도 루트가 아니거나 sudo를 사용하여 명령에 대한 올바른 결과를 얻을 수 있습니다. 특권없이 때로는 오류가 없으며 결과가 적습니다.

마지막으로 프로세스가 파일 시스템에서 액세스하는 ‘파일’을 알고 싶다면 다음을 살펴보십시오. lsof -p {PID} | grep / | awk ‘{print $ 9}’| 정렬 | 유니크

재미있게 보내세요!


답변