Em determinadas situações de missão crítica, os servidores Linux geram uma exceção "Too many files open". Este tipo de problema ocorre quando determinado usuário (inclusive o root) alcança o limite máximo de abertura de arquivos permitida pelo sistema.
Como monitorar a quantidade de arquivos abertos?
Através do comando lsof (list open files) é possível verificar todos os arquivos abertos no sistema – incluindo aqueles sem "descritores", ou seja, bibliotecas mapeadas em memória, diretórios, executáveis, entre outros.
Um descritor de um arquivo é um dado estruturado usado pelos programas para buscar uma referência ao arquivo. Em relação a performance do sistema, arquivos sem descritores não impactam no limite de arquivo que poderá ser aberto pelos usuários. Através desse comando, temos uma visão geral. Por exemplo, para saber a quantidade de arquivos abertos (incluindo aqueles sem descritores) do usuário "tomcat", podemos utilizar o comando:
lsof | grep tomcat | wc -l
Para verificarmos a quantidade de arquivos abertos com os descritores - aqueles que provocam a exceção, utilize o comando abaixo:
cat /proc/sys/fs/file-nr
Este comando irá exibir uma mensagem similar a apresentada abaixo:
3584 0 406486
Estas colunas, respectivamente, representam o seguinte:
Primeira coluna (3584) - Total de descritores alocados.
Segunda coluna (0) - Dos descritores alocados (na primeira coluna), este número indica quanto deles estão livres.
Terceira coluna (406486) - Total de descritores que podem ser alocados.
Observação: Existe certa especulação a respeito da segunda coluna. Algumas pessoas dizem que ela representa o número de descritores alocados, mas é justamente o contrário. Ela indica o número livre de descritores, dos alocados. Neste exemplo, temos 3584 descritores alocados, sendo que nenhum deles está livre, e o sistema poderá alocar 406486.
Para encontrar o número de arquivos abertos (com descritores) no sistema, pegue a primeira coluna e subtraia da segunda (3584 - 0). Neste caso particular (servidor de missão crítica em produção - com um SGBD MySQL e um Container J2SE rodando), não existem descritores livres.
Quantos arquivos (com descritores) um determinado usuário poderá abrir?
Com o comando abaixo, podemos descobrir o número máximo de arquivos que um usuário pode abrir através da linha "open files".
Observe que o comando deve ser executado pelo próprio usuário.
ulimit -a
O comando exibirá a seguinte tabela (este comando foi realizado por um usuário comum de micro desktop):
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 7679
max locked memory (kbytes, -l) 32
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 7679
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
Observe que a linha "open files" apresenta um limite de 1024 arquivos (com descritores).
Entendendo o problema:
Quando uma exceção "Too many open files" ocorre, significa que, o número de arquivos (com descritores) que foram abertos pelo usuário ultrapassou o limite estabelecido em "open files" do comando "ulimit -a". Lembre-se que o limite de "lsof | grep usuario | wc -l" representa um valor muito acima de arquivos abertos por "usuario".
Como obter o real número de arquivos abertos:
Podemos obter quais processos estão sendo utilizados pelo usuário com o comando (faça as devidas adaptações no "cut" para indicar somente o valor de id do processo no resultado completo de "lsof | grep guilherme":
lsof | grep guilherme | cut -c11-15 | uniq
Podemos então, para cada processo exibido, verificar quais arquivos com descritores estão abertos com o comando (para o processo de PID 6340):
ls -l /proc/6340/fd/
E o total de arquivos abertos para aquele processo com:
lsof | grep guilherme | wc -l
Enfim, não é tão simples assim descobrir a quantidade de arquivos com descritores abertos por determinado usuário.
Podemos fazer isso com o script abaixo:
#!/bin/sh
##########################################################################
# SCRIPT que conta o número de arquivos abertos pelo usuário "C_USER"
C_USER=guilherme
TOTAL=0
for iFile in `lsof | grep $C_USER | cut -c11-15 | uniq`
do
VALOR=`ls -l /proc/$iFile/fd/ | wc -l`
TOTAL=$(($VALOR + $TOTAL))
done
echo
echo "Total de arquivos abertos pelo usuário $C_USER: $TOTAL"
echo
##########################################################################
Com esse SCRIPT podemos saber exatamente quantos arquivos com descritores estão abertos pelo usuário. Rodando esse script no meu micro, o resultado apresentado foi:
Total de arquivos abertos pelo usuário guilherme: 826
OBS. O comando "cut" pega exatamente as colunas que representam o número do processo. Para validar o script acima, execute o comando abaixo e verifique se o PID dos processos foi recuperado com sucesso (talvez seja necessário alterar para "cut -c11-16")
lsof | grep guilherme | cut -c11-15
Voltando ao assunto que interessa.
O valor apresentado por esse script sempre deverá ser inferior ao "open files" do comando "ulimit -a", caso contrário:
Too many open files
Resolvendo o problema:
Aumentar o limite máximo de arquivos com descritores que podem ser abertos pelo usuário que impactou no problema. Como podemos fazer isso?
Acrescente as linhas abaixo no arquivo "/etc/security/limits.conf" para o respectivo usuário (neste caso, guilherme):
guilherme soft nofile 2048
guilherme hard nofile 63536
O limite soft, é o limite máximo suportado pelo usuário. Porém, o usuário poderá aumentar esse limite até o limite "hard". Esses limites são definidos pelo root, e o usuário em questão poderá aumentar seu limite além do soft (2048, neste caso) com o comando:
ulimit -n 2048
Obrigado pela leitura.
Nenhum comentário:
Postar um comentário