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


13

최근 서버에 파일 설명자가 부족하여 질문이 있습니다. 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)를 제공하므로 올바른 방향의 단계처럼 보입니다. "안타깝게도"파일 디스크립터 부족 문제가 발생하지 않으므로이를 확인하는 데 어려움이 있습니다.


2
lsof는 열린 파일뿐만 아니라 메모리 매핑도보고하므로 'wc'파이프 라인은 해당 프로세스에서 사용하는 파일 설명자 수를 과대 평가합니다.
Richard Kettlewell

아하! 지금은 좋은 정보입니다. 그러나 나는 확실히 이해하지 못한다. "메모리 매핑"이란 메모리 매핑 파일을 의미합니까? 내 이해를 위해 파일 핸들이 필요합니까? 아니면 OS가 파일을 어떻게 업데이트 할 수 있습니까?
oligofren

그리고 후속 조치 2 : 열려있는 모든 파일 핸들을 찾는 좋은 방법은 무엇입니까? "ulimit -n"에 의해 부과 된 한계에 실제로 영향을받는 핸들은 무엇입니까?
oligofren

1
메모리 매핑에는 열린 파일이 필요하지 않습니다. 열린 파일 만 나열하려면 lsof의 출력을 필터링하는 것이 가장 쉬운 방법 일 것입니다.
Richard Kettlewell

고마워, 내 대답을 편집했다. "lsof -u root | grep / | sort -k9 -u"를 사용하면 어느 정도의 합리적인 대답을하는 것처럼 보입니다. 최소한 ulimit -n보다 작은 수입니다.
oligofren

답변:


9

나는 이것을 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 : 프로세스 로그에 열린 파일이 너무 많습니다)


이것을 테스트 해 주셔서 감사합니다. 왜 lsof -p$PidOfGlassfish|wc -l1300을 주 었는지 아십니까? 계산에 대한 두 가지 접근 방식이 어떻게 든 다른지 추측합니다. 그렇지 않다면 아마도 루트 사용자에게 제한이 적용되지 않습니까?
oligofren

그냥 궁금해서 왜 ls -l대신 사용 ls합니까? 후자는 total 55 개의 파일이있을 때 추가 라인 (예 :)을 갖습니다 . 이 경우 ls -l 위의 예에서 6을 사용하지 않고 6을보고합니다 ls /proc/<pid>/fd | wc -l.
starfry

@starfry 그건 내 부분에 멍청한 짓이야. 나는 보통 이것을 단계별로 수행하고 ls -l한 줄에 하나의 항목을 주면 다른 것으로 파이프합니다. cours의 경우, 이는 배관이 정상일 때도 발생합니다 ls(그렇지 않으면).
oligofren

3

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

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


3

@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의미 하는지 문서화합니다 .


0

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

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


나는 당신이 나를 어떻게 해석 할 수 있는지 잘 모르겠습니다. :-) 내가 궁금한 것은 그것이 적용되지 않는 이유입니다. 더 높게 설정하지만 어떻게 작동하는지 이해하고 싶습니다. 제한이 1024 인 경우 Glassfish는 어떻게 1300 핸들을 가질 수 있습니까?
oligofren

'lsof -u root | grep / | sort -k9 -u'는 고유 한 파일 디스크립터 항목을 인쇄합니다. 이것의 줄 수가 ulimit -n이 적용되는 실제 숫자라고 생각합니다.
oligofren

0

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


1
bash에 대한 의견은 정확하지 않습니다. ulimit는 쉘을 통해 시작된 프로세스에 대해 사용자 ID 당 한도 세트를 부과합니다. 이는 운영 체제와 같은 Unix에서 프로세스 트리가 생성되는 방식 덕분에 사실상 모든 것입니다. 배쉬가 아닙니다.
EightBitTony 2016 년

죄송합니다-편집 하겠지만 시스템 전체 제한에 대한 의견은 여전히 ​​유효합니다.
rnxrx 2016 년

그가 시스템 전체 한계에 도달 할 가능성은 거의 없습니다. 가능하지만 매우 가능성이 낮습니다.
David Schwartz 2016 년

EightBitTony : ulimit는 사용자 ID 제한 집합 당 ulimit를 설정하지 않습니다. pam_limits가 적용될 때 프로세스 당입니다. "사용자 별"인 ulimit는 "ulimit -u"입니다. "단일 사용자가 사용할 수있는 최대 프로세스 수"
이름 없음

0

원시 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}'| 정렬 | 유니크

재미있게 보내세요!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.