Nosso servidor recentemente ficou sem descritores de arquivo e, com 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. Verifiquei o número de descritores de arquivos abertos executando lsof -u root |wc -l
e obtive 2500 fds. Isso é muito mais que 1024, então imaginei que o número 1024 é por processo, não por usuário, como eu pensava. Bem, eu corri lsof -p$PidOfGlassfish|wc -l
e consegui 1300. Esta é a parte que não entendo. Se ulimit -n
não for 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 se sim, como eu poderia receber as mensagens de erro sobre a falta de descritor de arquivo?
EDIT: A única maneira de entender ulimit -n
é se ele aplica o número de arquivos abertos (como indicado no manual do bash) em vez do número de identificadores de arquivos (processos diferentes podem abrir o mesmo arquivo). Se for esse o caso, basta listar o número de arquivos abertos (grepping em '/', excluindo assim os arquivos mapeados na memória) não é suficiente:
lsof -u root |grep /|sort -k9 |wc -l #prints '1738'
Para realmente ver o número de arquivos abertos, eu precisaria filtrar a coluna de nome para imprimir apenas as entradas exclusivas. Portanto, o seguinte é provavelmente mais correto:
lsof -u root |grep /|sort -k9 -u |wc -l #prints '604'
O comando acima espera 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 ser um passo na direção certa. "Infelizmente" não estou tendo problemas com a falta de descritores de arquivos, portanto, dificilmente validarei isso.
fonte
Respostas:
Eu testei isso no Linux versão 2.6.18-164.el5 - Red Hat 4.1.2-46. 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
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 para 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 nos logs do processo)
fonte
lsof -p$PidOfGlassfish|wc -l
me deu 1300? Eu estou supondo que as duas abordagens para contar diferem de alguma forma. Caso contrário, talvez o limite não se aplique ao usuário root?ls -l
vez dels
? Este último possui uma linha extra (por exemplototal 5
) quando existem 5 arquivos. Nesse caso, o usols -l
no exemplo acima relataria 6 e não 5. Eu usols /proc/<pid>/fd | wc -l
.ls -l
me fornece uma entrada por linha, que depois canalizo para outra coisa. É claro que isso também acontece quando a tubulação é normalls
(mas não de outra forma).O ulimit é para identificadores de arquivo. Aplica-se a arquivos, diretórios, soquetes, epolls de tubos, 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.fonte
@oligofren
I também realizou alguns testes para determinar como
"ulimits -Sn"
para"open files"
foi cumprida.Como o pôster Escolhido mencionado no link , o ulimit for
"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 do exposto e meu método / resultados de teste
Os
"-P -M -l -n"
argumentos para lsof estão lá simplesmente para fazer lsof operar o mais rápido possível. Sinta-se livre para tirá-los.O
"-d '^cwd,^err,^ltx,^mem,^mmap,^pd,^rtd,^txt'"
argumento instruilsof
a excluir descritores de arquivo do tipo: cwd / err / ltx / mem / mmap / pd / rtd / txt.Na página do manual lsof:
Eu considerei
"Lnn,jld,m86,tr,v86"
não aplicável ao Linux e, portanto, não me preocupei em adicioná-los à lista de exclusão. Eu não tenho certeza"Mxx"
.Se seu aplicativo utiliza arquivos / dispositivos mapeados na memória, convém remover
"^mem"
e"^mmap"
da lista de exclusão.EDITAR --- começar recortar ---
Editar: Encontrei o seguinte link que indica que:
Portanto, se o seu processo usar arquivos mapeados na memória, será necessário filtrar os arquivos * .so.
Além disso, a JVM da Sun armazenará arquivos jar de memória
Portanto, coisas como tomcat / glassfish também mostrarão arquivos jar mapeados na memória. Eu não testei se isso conta até o
"ulimit -Sn"
limite.EDIT --- final snip ---
Empiricamente, descobri que não
"cwd,rtd,txt"
são contados com relação ao limite de arquivos por processo (ulimit -Sn).Não tenho certeza se
"err,ltx,pd"
são contados no limite do arquivo, pois não sei como criar identificadores de arquivo desses tipos de descritores.O
"-p __process_id__"
argumento se restringelsof
a retornar apenas informações para o__process_id__
especificado. Remova isso se desejar obter uma contagem para todos os processos.O
"-a"
argumento é usado para AND nas seleções (ou seja, os argumentos "-p" e "-d").A
"awk '{if (NR>1) print}'"
instrução é usada para pular o cabeçalho que élsof
impresso em sua saída.Eu testei usando o seguinte script perl:
Eu tive que executar o script no depurador perl para garantir que o script não termine e libere os descritores de arquivo.
Executar:
perl -d test.pl
No depurador do perl, você pode executar o programa digitando
c
e pressionando enter e, se vocêulimit -Sn
tiver um valor de 1024 , verá que o programa para após a criação doTest1017.log
arquivo/tmp
.Se você agora identificar o pid do processo perl e usar o
lsof
comando acima , verá que ele também gera 1024 .Remova
"wc -l"
e substitua por a"less"
para ver a lista de arquivos contados no limite de 1024 . Remova o"-d ^....."
argumento também para ver que os descritorescwd,txt
e não contam para o limite.rtd
Se você executar agora
"ls -l /proc/__process_id__/fd/ | wc -l"
, verá um valor de 1025 retornado. Isso ocorre porque foils
adicionado um"total 0"
cabeçalho à saída que foi contado.Nota:
Para verificar se o sistema operacional está ficando sem descritores de arquivo, é melhor comparar o valor de:
cat /proc/sys/fs/file-nr | awk '{print $1}'
com
cat /proc/sys/fs/file-max
https://www.kernel.org/doc/Documentation/sysctl/fs.txt documenta o que
file-nr
e o quefile-max
significa.fonte
Parece que seu raciocínio é algo como "eu tenho que diminuir esse limite para não ficar com descritores preciosos". A verdade é exatamente o contrário - se o servidor ficou sem descritores de arquivo, você precisa aumentar esse limite de 1.024 para algo maior. Para uma
glassfish
implementação realista , 32.768 é razoável.Pessoalmente, sempre elevo o limite para cerca de 8.192 em todo o sistema - 1.024 é simplesmente ridículo. Mas você vai querer aumentar
glassfish
mais. Verifique/etc/security/limits.conf
. Você pode adicionar uma entrada especial para o usuárioglassfish
executar como.fonte
Você quer dar uma olhada nos limites de todo o sistema definidos em / proc / sys / fs / file-max e ajustá-lo lá (até a próxima reinicialização) ou definir fs.file-max no sysctl.conf para torná-lo permanente. Isso pode ser útil - http://www.randombugs.com/linux/tuning-file-descriptors-limits-on-linux.html
fonte
Erro comum ao comparar o resultado da chamada lsof bruta com o suposto limite.
Para o limite global (/ proc / sys / fs / file-max), consulte / 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, consulte o comando "ulimit -Hn" para limites do usuário e consulte /etc/security/limits.conf para obter definições. Geralmente aplicado com "usuário do aplicativo", por exemplo: "tomcat": defina o limite de 65000 para o usuário tomcat, que será aplicado no processo java executado.
Se você deseja verificar o limite aplicado em um processo, obtenha seu PID e, em seguida: cat / proc / $ {PID} / limits Se você deseja verificar quantos arquivos são abertos por um processo, obtenha seu PID e, em seguida: ls -1 / proc / {PID} / fd | wc -l (note que ls é 'menos um', para não confundir com 'menos el')
Se você quiser saber detalhes com lsof, mas apenas para os manipuladores de arquivos que contam para o limite, tente estas opções: 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 / conexões pipe / tcp / etc.
Observe que às vezes você provavelmente precisará ser root ou usar o sudo para obter o resultado correto para os comandos; sem privilégios, às vezes você não tem erro, apenas menos resultados.
e, finalmente, se você quiser saber quais 'arquivos' no seu sistema de arquivos são acessados por um processo, dê uma olhada em: lsof -p {PID} | grep / | awk '{print $ 9}' | classificar | uniq
diverta-se !
fonte