Por que (ou como) o número de descritores de arquivos abertos em uso pelo root excede ulimit -n?

12

Recentemente, nosso servidor ficou sem descritores de arquivos e, em relação a isso, tenho algumas perguntas. ulimit -n deve me fornecer o número máximo de descritores de arquivos abertos. Esse número é 1024. Eu verifiquei o número de descritores de arquivos abertos executando lsof -u root |wc -l e obtive 2500 fds. Isso é muito mais do que 1024, então eu imaginei que isso significaria que o número 1024 é por processo, não por usuário, como eu pensei. Bem, eu corri lsof -p$PidOfGlassfish|wc -l e tenho 1300. Esta é a parte que eu não entendo. Se ulimit -n não é o número máximo de processos por usuário ou por processo, para que serve? Não se aplica ao usuário root? E, em caso afirmativo, como eu poderia obter as mensagens de erro sobre a falta de descritor de arquivo?

EDIT: A única maneira que eu posso fazer sentido de ulimit -n é se aplica o número de arquivos abertos (como indicado no manual bash) ao invés do número de identificadores de arquivo ( processos diferentes podem abrir o mesmo arquivo). Se este for o caso, simplesmente listar o número de arquivos abertos (grepping em '/', excluindo arquivos mapeados na memória) é não sufficent:

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

Para realmente ver o número de arquivos abertos, eu precisaria filtrar na coluna de nome apenas para imprimir as entradas exclusivas. Assim, o seguinte é provavelmente mais correto:

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

O comando acima espera a saída no seguinte formato de 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

Isso pelo menos me dá um número menor que 1024 (o número relatado por ulimit -n ), então isso parece um passo na direção certa. "Infelizmente" não estou tendo problemas com a falta de descritores de arquivos, por isso vou ter dificuldade em validar isso.

    
por oligofren 08.06.2012 / 14:03

6 respostas

9

Eu testei isso na versão 2.6.18-164.el5 do Linux - Red Hat 4.1.2-46. Eu pude ver que o ulimit é aplicado por processo.

O parâmetro é definido no nível do usuário, mas aplicado a cada processo.

Por exemplo: 1024 era o limite. Vários processos foram iniciados e os arquivos abertos por cada um foram contados usando

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

Não houve erros quando a soma dos arquivos abertos por vários processos ultrapassou 1024. Também verifiquei a contagem de arquivos exclusivos, combinando os resultados de diferentes processos e contando arquivos exclusivos. Os erros começaram a aparecer apenas quando a contagem de cada processo ultrapassou 1024. (java.net.SocketException: muitos arquivos abertos em logs de processo)

    
por 24.09.2012 / 12:41
3

O ulimit é para filehandles. Aplica-se a arquivos, diretórios, sockets, pipes epolls, eventfds, timerfds etc etc.

A qualquer momento durante a inicialização do processo, os limites podem ter sido alterados. Visite /proc/<pid>/limits e veja se os valores foram alterados.

    
por 16.07.2012 / 17:53
3

@oligofren

Também realizei alguns testes para determinar como "ulimits -Sn" para "open files" foi aplicado.

  • Assim como o pôster Escolhido mencionado no link , o ulimit de "open files" é realmente aplicado por processo. Para ver quais são os limites atuais do processo:

    cat /proc/__process_id__/limits

  • Para determinar quantos arquivos um processo abriu, você precisa usar o seguinte comando:

    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

Explicação acima e do meu método de teste / resultados

Os argumentos "-P -M -l -n" para lsof estão simplesmente lá para fazer com que lsof opere o mais rápido possível. Sinta-se à vontade para tirá-los.

-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

O argumento "-d '^cwd,^err,^ltx,^mem,^mmap,^pd,^rtd,^txt'" instrui lsof a excluir os descritores de arquivo do tipo: cwd / err / ltx / mem / mmap / pd / rtd / txt.

Da lsof man page:

   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;

Considerei "Lnn,jld,m86,tr,v86" como não aplicável ao Linux e, portanto, não me preocupei em adicioná-los à lista de exclusão. Não tenho certeza sobre "Mxx" .

Se o seu aplicativo usar arquivos / dispositivos mapeados na memória, talvez você queira remover "^mem" e "^mmap" da lista de exclusões.

EDIT --- begin snip ---

Editar: achei o seguinte link que indica que:

memory mapped .so-files technically aren't the same as a file handle the application has control over. /proc//fd is the measuring point for open file descriptors

Portanto, se o seu processo usa arquivos mapeados na memória, você precisará filtrar os arquivos * .so.

Além disso, a JVM da Sun executará arquivos jar do mapa de memória

A memory-mapped JARfile, in this case the file that holds the "JDK classes." When you memory-map a JAR, you can access the files within it very efficiently (versus reading it from the start each time). The Sun JVM will memory-map all JARs on the classpath; if your application code needs to access a JAR, you can also memory-map it.

Assim, coisas como o tomcat / glassfish também mostram arquivos jar mapeados na memória. Não testei se estas contam para o limite "ulimit -Sn" .

EDIT --- fim do recorte ---

Empiricamente, descobri que "cwd,rtd,txt" são não contados em relação ao limite do arquivo por processo (ulimit -Sn).

Não tenho certeza se "err,ltx,pd" é contado para o limite de arquivo, pois não sei como criar identificadores de arquivo desses tipos de descritor.

O argumento "-p __process_id__" restringe lsof para retornar apenas informações para o __process_id__ especificado. Remova isso se você quiser obter uma contagem para todos os processos.

O argumento "-a" é usado para AND as seleções (isto é, os argumentos "-p" e "-d").

A instrução "awk '{if (NR>1) print}'" é usada para pular o cabeçalho que lsof imprime na saída.

Eu testei usando o seguinte script 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---

Eu tive que executar o script no depurador perl para garantir que o script não terminasse e liberasse os descritores de arquivo.

Para executar: perl -d test.pl

No depurador do perl, você pode executar o programa digitando c e pressionando Enter e, se o ulimit -Sn tiver um valor 1024 , você encontrará que o programa pára depois de criar o arquivo Test1017.log em /tmp .

Se você identificar o pid do processo perl e usar o comando lsof acima, verá que ele também gera 1024 .

Remova o "wc -l" e substitua por "less" para ver a lista de arquivos que contam para o limite de 1024 . Remova também o argumento "-d ^....." para ver que os descritores cwd,txt e rtd não contam para o limite.

Se você executar agora "ls -l /proc/__process_id__/fd/ | wc -l" , verá um valor de 1025 retornado. Isso ocorre porque ls adicionou um cabeçalho "total 0" à sua saída, que foi contada.

Nota:

Para verificar se o sistema operacional está ficando sem descritores de arquivos, é melhor comparar o valor de:

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

com

cat /proc/sys/fs/file-max

O

link documenta o que file-nr e file-max significam.

    
por 05.04.2016 / 19:15
0

Parece que seu raciocínio é algo como: "Eu tenho que diminuir esse limite para que eu não fique sem descritores preciosos". A verdade é exatamente o contrário - se o seu servidor ficar sem descritores de arquivos, você precisará aumentar esse limite de 1.024 para algo maior. Para uma implementação realista de glassfish , 32.768 é razoável.

Pessoalmente, eu sempre elevo o limite para cerca de 8.192 em todo o sistema - 1.024 é simplesmente ridículo. Mas você vai querer aumentar glassfish maior. Verifique /etc/security/limits.conf . Você pode adicionar uma entrada especial para o usuário glassfish é executado como.

    
por 08.06.2012 / 14:46
0

Você quer dar uma olhada nos limites de todo o sistema definidos em / proc / sys / fs / file-max e ajustá-los lá (até a próxima reinicialização) ou definir fs.file-max em sysctl.conf para torná-lo permanente. Isso pode ser útil - link

    
por 08.06.2012 / 14:23
0

Erro comum ao comparar o resultado de lsof de chamada com suposto limite.

Para o limite global (/ proc / sys / fs / file-max) você deve dar uma olhada em / proc / sys / fs / file-nr - > o primeiro valor indica o que é usado e o último valor é o limite

O limite do OpenFile é para cada processo, mas pode ser definido em um usuário, veja o comando "ulimit -Hn" para limites de usuários e veja /etc/security/limits.conf para definições. Geralmente aplicado com "usuário do aplicativo", por exemplo: "tomcat": defina o limite para 65000 para o usuário tomcat que será aplicado no processo java executado.

Se você quiser verificar o limite aplicado em um processo, obtenha seu PID e, em seguida: cat / proc / $ {PID} / limits Se você quiser verificar quantos arquivos são abertos por um processo, obtenha seu PID e, em seguida: ls -1 / proc / {PID} / fd | wc -l (nota para ls é 'menos um', não para confundir com 'menos el')

Se você quiser saber detalhes com o lsof, mas somente para os manipuladores de arquivos que contam para o limite, tente com estes: lsof -p $ {PID} | grep -P "^ (\ w + \ s +) {3} \ d + \ D +" lsof -p $ {PID} -d '^ cwd, ^ err, ^ ltx, ^ mem, ^ mmap, ^ pd, ^ rtd, ^ txt' -a

Observação: os 'arquivos' são arquivos / pipe / tcp / etc.

Note que às vezes você provavelmente precisará ser root ou usar o sudo para obter resultados corretos para os comandos, sem privilégios às vezes você não tem erros, apenas menos resultados.

e, finalmente, se você quiser saber quais arquivos do seu sistema de arquivos são acessados por um processo, dê uma olhada em: lsof -p {PID} | grep / | awk '{print $ 9}' | ordenar | uniq

divirta-se!

    
por 26.04.2019 / 16:07