15%

Poupe 15% em todos os serviços

Teste as suas habilidades e obtenha Desconto em qualquer plano

Utilizar o código:

Skills
Começar a trabalhar
09.10.2024

Gerenciando Recursos do Sistema com o Comando `ulimit` no Linux

O comando `ulimit` é um utilitário de shell integrado em sistemas Unix e Linux que impõe limites de recursos por processo e por utilizador, impedindo que um único processo ou utilizador esgote os recursos do sistema, como tempo de CPU, memória, descritores de ficheiros abertos e contagem de processos. Funciona ao nível do kernel através da chamada de sistema `setrlimit()`, tornando-o um dos mecanismos mais diretos e de baixo overhead disponíveis para os administradores de sistemas na gestão de recursos.

Para qualquer servidor que execute cargas de trabalho em produção — seja uma aplicação web de alto tráfego, um motor de base de dados ou uma pilha de microsserviços em contentores — as definições `ulimit` mal configuradas ou ausentes são uma das principais causas de falhas em cascata, processos descontrolados e interrupções totais do sistema. Configurar corretamente estes limites não é opcional; é uma higiene de infraestrutura fundamental.

Como o `ulimit` Funciona Internamente

Quando um processo de shell chama `ulimit`, invoca as chamadas de sistema `getrlimit()` e `setrlimit()` definidas no padrão POSIX. Cada limite é representado como um par de valores: um limite suave e um limite rígido. Estes são armazenados por processo no descritor de processo do kernel e são herdados pelos processos filhos no momento do `fork()`.

Este modelo de herança é fundamental para compreender. Se definir valores `ulimit` numa sessão de shell, todos os processos gerados a partir desse shell — incluindo daemons lançados via scripts de init — herdam esses limites. Por outro lado, os limites definidos em `/etc/security/limits.conf` aplicam-se no momento do login PAM, não em tempo de execução, o que significa que só entram em vigor para novas sessões de login, não para serviços já em execução.

Limites Suaves vs. Limites Rígidos

PropriedadeLimite SuaveLimite Rígido
Quem pode aumentá-loQualquer utilizador sem privilégios (até ao limite rígido)Apenas root (`CAP_SYS_RESOURCE`)
Quem pode reduzi-loQualquer utilizadorQualquer utilizador (irreversível sem root)
AplicaçãoAplicado pelo kernelFunciona como teto para o limite suave
Caso de uso típicoLimite operacional do dia a diaMáximo absoluto para política de segurança
Flag em `ulimit``-S``-H`

Um erro operacional comum é definir o limite rígido igual ao limite suave. Isto remove toda a flexibilidade para um processo aumentar temporariamente os seus próprios limites, o que algumas aplicações (como certas implementações de JVM e motores de base de dados) fazem legitimamente durante o arranque.

Referência Completa: Flags de Recursos do `ulimit`

FlagRecursoUnidadeValor Comum em Produção
`-t`Tempo de CPUSegundos`unlimited` para daemons
`-f`Tamanho máximo de ficheiroBlocos de 512 bytes`unlimited` ou limite específico
`-d`Tamanho do segmento de dados (heap)KB`unlimited` para aplicações Java
`-s`Tamanho da pilhaKB`8192` (predefinição)
`-c`Tamanho do ficheiro de core dumpBlocos de 512 bytes`0` (desativado em produção)
`-m`Tamanho máximo do conjunto residenteKBRaramente aplicado (usar cgroups)
`-v`Memória virtual (espaço de endereços)KB`unlimited` para a maioria dos serviços
`-n`Descritores de ficheiros abertosContagem`65536` ou superior para servidores com muito tráfego
`-u`Máximo de processos de utilizadorContagem`4096`–`65536` dependendo da função
`-l`Memória bloqueada (mlock)KBAlto para Redis, Elasticsearch
`-i`Sinais pendentesContagemPredefinição do sistema geralmente suficiente
`-q`Bytes da fila de mensagens POSIXBytesPredefinição do sistema
`-r`Prioridade de agendamento em tempo realPrioridade`0` exceto para cargas de trabalho RT
`-e`Prioridade máxima de agendamento (nice)Valor nicePredefinição do sistema

Utilização Prática do `ulimit` com Contexto Real

Visualizar os Limites Atuais

“`bash

ulimit -a # All soft limits for the current shell

ulimit -aH # All hard limits for the current shell

“`

Para inspecionar os limites de um processo em execução específico (PID), leia diretamente do sistema de ficheiros proc — esta é a fonte autoritativa e contorna os relatórios ao nível do shell:

“`bash

cat /proc/<PID>/limits

“`

Isto é inestimável ao resolver problemas de um serviço iniciado pelo systemd ou por um script de init, onde o `ulimit -a` ao nível do shell não refletirá os limites reais do processo.

Definir Limites Suaves e Rígidos

“`bash

Set soft limit for open file descriptors

ulimit -Sn 65536

Set hard limit for open file descriptors

ulimit -Hn 131072

Set both simultaneously (soft = hard = value)

ulimit -n 65536

“`

Desativar Core Dumps em Produção

“`bash

ulimit -c 0

“`

Os core dumps podem consumir gigabytes de espaço em disco em segundos quando um processo com muita memória falha. Desativá-los em produção é uma prática padrão, a menos que esteja a depurar ativamente. Para ambientes de desenvolvimento, defina um caminho dedicado usando `sysctl kernel.core_pattern` juntamente com um limite de core não nulo.

Restringir o Tempo de CPU para Processos Não Confiáveis

“`bash

ulimit -t 30

“`

Isto envia `SIGXCPU` ao processo quando atinge o limite suave de tempo de CPU, e `SIGKILL` no limite rígido. Isto é particularmente útil em ambientes de alojamento partilhado ou ao executar scripts submetidos por utilizadores.

Aumentar o Limite de Descritores de Ficheiros Abertos para Serviços de Alta Concorrência

Nginx, HAProxy, PostgreSQL e Redis requerem um elevado número de descritores de ficheiros abertos sob carga. A predefinição do sistema de 1024 é perigosamente baixa para produção:

“`bash

ulimit -n 65536

“`

No entanto, isto apenas afeta a sessão de shell atual. Para configuração persistente, utilize os métodos descritos na secção seguinte.

Tornar as Definições do `ulimit` Persistentes

Método 1: `/etc/security/limits.conf`

Esta é a abordagem padrão baseada em PAM para limites persistentes ao nível do utilizador:

“`

/etc/security/limits.conf

<domain> <type> <item> <value>

  • soft nofile 65536
  • hard nofile 131072

nginx soft nproc 4096

nginx hard nproc 8192

postgres soft nofile 65536

postgres hard nofile 65536

postgres soft memlock unlimited

postgres hard memlock unlimited

“`

O wildcard `*` aplica-se a todos os utilizadores mas não se aplica ao root. O root requer uma entrada explícita:

“`

root soft nofile 65536

root hard nofile 131072

“`

Certifique-se de que o módulo PAM está carregado. Verifique se `/etc/pam.d/common-session` (Debian/Ubuntu) ou `/etc/pam.d/system-auth` (RHEL/CentOS) contém:

“`

session required pam_limits.so

“`

Método 2: Ficheiros Drop-in do `/etc/security/limits.d/`

Para uma gestão mais limpa, especialmente em sistemas de gestão de configuração como Ansible ou Puppet, coloque ficheiros de limites específicos do serviço no diretório drop-in:

“`bash

/etc/security/limits.d/99-nginx.conf

nginx soft nofile 65536

nginx hard nofile 131072

“`

Os ficheiros neste diretório são processados após `limits.conf` e substituem-no, tornando-os ideais para ajuste específico de aplicações sem modificar a configuração base.

Método 3: Unidades de Serviço systemd (O Padrão Moderno)

Para serviços geridos pelo systemd — que é a maioria das distribuições Linux modernas — `limits.conf` não é aplicado por predefinição. O systemd gere os seus próprios limites de recursos por unidade de serviço:

“`ini

/etc/systemd/system/nginx.service.d/limits.conf

[Service]

LimitNOFILE=65536

LimitNPROC=4096

LimitCORE=0

LimitMEMLOCK=infinity

“`

Após editar, recarregue e reinicie:

“`bash

systemctl daemon-reload

systemctl restart nginx

“`

Verifique os limites aplicados:

“`bash

cat /proc/$(systemctl show -p MainPID nginx | cut -d= -f2)/limits

“`

Este é o método mais fiável para serviços em produção e deve ser a abordagem padrão em qualquer sistema que execute systemd (Ubuntu 16.04+, CentOS 7+, Debian 8+).

Método 4: Ficheiros de Perfil do Shell

Para limites de sessão de utilizador que se aplicam interativamente, adicione comandos `ulimit` a `/etc/profile` (para todo o sistema) ou `~/.bashrc` / `~/.profile` (por utilizador). Esta abordagem é adequada para estações de trabalho de desenvolvimento, mas não é adequada para processos daemon.

Perfis de Configuração do `ulimit` Baseados em Função

Diferentes funções de servidor exigem perfis de limites de recursos fundamentalmente diferentes. Aplicar predefinições genéricas em todos os tipos de servidor é uma fonte comum de falhas subtis e difíceis de diagnosticar.

Servidor Web (Nginx / Apache)

“`

nofile: 65536–131072 # High concurrency requires many open sockets + files

nproc: 4096 # Worker processes + threads

core: 0 # Disable core dumps in production

“`

Base de Dados Relacional (PostgreSQL / MySQL)

“`

nofile: 65536 # Many concurrent connections = many file descriptors

memlock: unlimited # Required for shared memory and huge pages

nproc: 4096

stack: 8192 KB

core: 0

“`

Servidor de Aplicações Java (Tomcat / Spring Boot)

“`

nofile: 65536

nproc: 65536 # JVM thread-per-connection models spawn many threads

data: unlimited # JVM heap is allocated from the data segment

stack: 512 KB # Reduce stack size to fit more threads in memory

“`

Redis / Armazenamento de Dados em Memória

“`

nofile: 65536

memlock: unlimited # Prevents swapping of memory-mapped data

“`

Armadilhas Críticas e Casos Extremos

O limite `nproc` conta threads, não apenas processos. No Linux, as threads são implementadas como processos leves (`clone()` com memória partilhada). Uma aplicação Java com 500 threads conta como 500 contra o limite `nproc`. Isto surpreende muitos administradores que definem valores conservadores de `nproc` e depois ficam a perguntar-se por que razão a sua JVM falha com `OutOfMemoryError: unable to create new native thread`.

`ulimit -v` limita o espaço de endereços virtual, não a RAM física. Muitos administradores definem `-v` pensando que estão a limitar o uso de memória. Na realidade, estão a limitar o espaço de endereços virtual, que inclui ficheiros mapeados em memória, bibliotecas partilhadas e metaspace da JVM. Definir este valor demasiado baixo causará falhas de `mmap()` e erros de aplicação crípticos.

`ulimit` não se aplica retroativamente. Alterar limites em `limits.conf` ou num ficheiro de unidade systemd não afeta os processos já em execução. Tem de reiniciar o serviço para que os novos limites entrem em vigor.

Os ambientes de contentores contornam o `ulimit` de formas inesperadas. No Docker, as predefinições do `ulimit` são definidas ao nível do daemon (`/etc/docker/daemon.json`) e podem ser substituídas por contentor com `–ulimit`. No entanto, os limites do contentor são delimitados pelos limites do kernel do host. Definir `nofile=1048576` num contentor enquanto o host tem `nofile=65536` reverterá silenciosamente para o limite do host.

O teto do sistema `nofile` é separado dos limites por processo. O parâmetro do kernel `fs.file-max` (definido via `sysctl`) controla o número total de descritores de ficheiros em todo o sistema. Mesmo que o `nofile` por processo esteja definido alto, atingir `fs.file-max` causará erros `ENFILE` em todo o sistema. Verifique e ajuste ambos:

“`bash

sysctl fs.file-max

sysctl -w fs.file-max=2097152

“`

`ulimit` vs. cgroups: Escolher a Ferramenta Certa

Capacidade`ulimit` / `setrlimit`cgroups v2
ÂmbitoPor processo (herdado pelos filhos)Por grupo de processos
Limitação de memóriaApenas espaço de endereços virtual (`-v`)Aplicação real de RSS + swap
Limitação de CPUOrçamento de tempo de CPU (`-t`)Controlador de largura de banda CPU (% precisa)
Limitação de I/ONão suportadoPeso e limites de taxa de I/O de bloco
Limitação de redeNão suportadoRequer integração tc + cgroup
PersistênciaVia PAM ou systemdVia slices systemd ou cgroupfs
Compatibilidade com contentoresLimitadaNativa (Docker, Kubernetes usam cgroups)
GranularidadeGrosseiraGranularidade fina

`ulimit` continua a ser a ferramenta certa para limites rápidos por sessão, limites de descritores de ficheiros e controlo de core dumps. Para isolamento abrangente de recursos — especialmente em ambientes multi-tenant ou cargas de trabalho em contentores — cgroups v2 é o mecanismo superior. Num ambiente de Alojamento VPS ou Servidor Dedicado bem configurado, ambos os mecanismos são tipicamente utilizados em combinação: `ulimit` para proteções por processo e cgroups para orçamentos de recursos agregados.

Monitorização e Validação de Limites de Recursos

A monitorização proativa previne que falhas relacionadas com limites se tornem incidentes em produção.

Verificar o uso atual de descritores de ficheiros em todo o sistema:

“`bash

cat /proc/sys/fs/file-nr

Output: <allocated> <unused> <max>

“`

Encontrar processos que se aproximam do seu limite `nofile`:

“`bash

for pid in /proc/[0-9]*; do

pid_num=${pid##*/}

limit=$(awk '/Max open files/{print $4}' /proc/$pid_num/limits 2>/dev/null)

current=$(ls /proc/$pid_num/fd 2>/dev/null | wc -l)

[ -n "$limit" ] && [ "$limit" != "unlimited" ] &&

awk -v c=$current -v l=$limit -v p=$pid_num

'BEGIN{if(c/l>0.8) printf "PID %s: %d/%d (%.0f%%)n",p,c,l,c/l*100}'

done

“`

Ferramentas para monitorização contínua:

  • `lsof -u <username>` — listar todos os ficheiros abertos para um utilizador
  • `ss -s` — estatísticas de socket (correlaciona com pressão `nofile`)
  • `htop` com vista de árvore de processos — visualizar contagens de processos por utilizador
  • `sar -v` — uso histórico de descritores de ficheiros e inodes via sysstat
  • Prometheus `node_exporter` — expõe métricas `node_filefd_allocated` e `node_filefd_maximum` para alertas

Para ambientes que executam VPS com cPanel ou outros painéis de controlo, muitos destes limites são pré-configurados pelo instalador do painel, mas frequentemente necessitam de ajuste ascendente à medida que o tráfego cresce. Verifique sempre os limites reais em `/proc/<PID>/limits` em vez de confiar na documentação do painel.

Implicações de Segurança do `ulimit`

Os limites de recursos são também um controlo de segurança. Sem eles, um processo comprometido ou com erros pode executar uma fork bomb (`:(){ :|:& };:`), esgotando todos os slots de processo disponíveis e tornando o sistema irresponsivo. Um limite conservador de `nproc` por utilizador é a principal mitigação:

“`

  • hard nproc 4096

“`

Da mesma forma, desativar os core dumps (`-c 0`) impede que conteúdos sensíveis da memória — incluindo chaves de encriptação, palavras-passe e tokens de sessão — sejam escritos em disco num ficheiro legível por todos.

Para ambientes de alojamento partilhado ou qualquer servidor onde múltiplos utilizadores têm acesso ao shell, `ulimit` é uma camada de segurança obrigatória. Na infraestrutura de Alojamento Web Partilhado, estes limites são tipicamente aplicados ao nível da plataforma, mas os administradores que executam o seu próprio VPS multi-utilizador devem configurá-los explicitamente.

Se o seu servidor lida com terminação SSL ou gestão de certificados, certifique-se de que o processo que trata TLS (por exemplo, Nginx, HAProxy) tem limites `nofile` suficientes, pois cada ligação TLS requer múltiplos descritores de ficheiros. Combine isto com Certificados SSL corretamente configurados para evitar que falhas relacionadas com certificados agravem os problemas de recursos.

Para implementações de servidores de correio, o Postfix e o Dovecot são particularmente sensíveis aos limites `nofile`, pois cada ligação de e-mail simultânea e acesso a caixa de correio consome descritores de ficheiros. Se estiver a executar a sua própria infraestrutura de correio em vez de usar Alojamento de E-mail gerido, ajustar `nofile` para pelo menos 65536 para o utilizador de correio é inegociável em qualquer servidor com carga moderada.

Matriz de Decisão: O Que Configurar e Onde

CenárioMétodo RecomendadoParâmetros Chave
Sessões de utilizador interativas`/etc/security/limits.conf``nofile`, `nproc`, `core`
Serviço gerido pelo systemdSecção `[Service]` da unidade systemd`LimitNOFILE`, `LimitNPROC`, `LimitCORE`
Contentor DockerFlag `–ulimit` ou `daemon.json``nofile`, `nproc`
Teste de shell únicoComando `ulimit` diretamenteQualquer flag
Servidor partilhado multi-tenant`limits.conf` + aplicação PAM`nproc`, `nofile`, `fsize`, `cpu`
Pod KubernetesContexto de segurança do pod + cgroupsGerido pelo kubelet
Ajuste específico de aplicaçãoFicheiro drop-in `limits.d/`Parâmetros específicos do serviço

Lista de Verificação de Pontos-Chave Técnicos

  • Verifique sempre os limites aplicados via `/proc/<PID>/limits`, não via `ulimit -a` ao nível do shell, para serviços em execução.
  • Para serviços systemd, configure os limites no ficheiro de unidade usando diretivas `Limit*` — `limits.conf` não é lido pelo systemd por predefinição.
  • Defina `nofile` para no mínimo `65536` para qualquer serviço que lide com ligações de rede; `131072` ou superior para cargas de trabalho de alta concorrência.
  • Nunca defina o limite rígido igual ao limite suave, a menos que tenha um requisito de segurança específico — as aplicações precisam de margem para se auto-ajustarem.
  • Desative os core dumps (`LimitCORE=0`) em produção; ative-os com um caminho controlado em staging.
  • O limite `nproc` conta threads no Linux — tenha isso em conta ao configurar aplicações JVM ou runtime Go.
  • Ajuste `fs.file-max` via `sysctl` juntamente com os limites `nofile` por processo para evitar o esgotamento `ENFILE` em todo o sistema.
  • Em ambientes de contentores, os limites do kernel do host são o teto rígido — as definições `ulimit` ao nível do contentor não podem excedê-los.
  • Use cgroups v2 para aplicação de memória e I/O; use `ulimit` para limites de descritores de ficheiros, contagens de processos e controlo de core dumps.
  • Após qualquer alteração de limite em `limits.conf` ou ficheiros de unidade systemd, reinicie o serviço afetado e verifique com `/proc/<PID>/limits`.

FAQ

O `ulimit` aplica-se a processos root?

O wildcard `*` em `/etc/security/limits.conf` exclui explicitamente o root. Os processos root também contornam a aplicação de limites rígidos para a maioria dos tipos de recursos — o root pode aumentar os seus próprios limites rígidos. Para aplicar limites ao root, adicione uma entrada explícita `root` em `limits.conf`, embora muitos serviços do sistema a correr como root ignorem os limites aplicados pelo PAM se iniciados fora de uma sessão de login.

Por que razão a minha alteração em `limits.conf` não tem efeito num serviço em execução?

`limits.conf` é aplicado pelo PAM no momento do login. Os serviços iniciados pelo systemd, SysVinit ou Upstart não passam pelo PAM e, portanto, não herdam as definições `limits.conf`. Configure os limites diretamente no ficheiro de unidade systemd usando `LimitNOFILE` e diretivas relacionadas, depois execute `systemctl daemon-reload && systemctl restart <service>`.

Qual é o valor máximo que posso definir para `nofile`?

O máximo por processo é delimitado pelo parâmetro do kernel `fs.nr_open` (predefinição: 1.048.576 na maioria dos kernels). O total em todo o sistema é delimitado por `fs.file-max`. Pode aumentar `fs.nr_open` via `sysctl`, mas valores acima de 1.048.576 requerem recompilação do kernel em kernels mais antigos. Praticamente, 524.288 ou 1.048.576 cobre praticamente todos os casos de uso em produção.

Como verifico se um processo atingiu o seu limite `ulimit`?

Verifique o registo do kernel com `dmesg | grep -i "ulimit|RLIMIT|too many open|cannot allocate"`. Os registos da aplicação mostrarão tipicamente `EMFILE` (demasiados ficheiros abertos), `ENOMEM` (falha de alocação de memória) ou `EAGAIN` (recurso temporariamente indisponível). Faça referência cruzada com `/proc/<PID>/limits` e a contagem atual de descritores via `ls /proc/<PID>/fd | wc -l`.

O `ulimit` é suficiente para isolamento de recursos num ambiente multi-tenant?

Não. O `ulimit` fornece proteções por processo e por utilizador, mas não aplica limites de largura de banda de memória, I/O de disco ou débito de rede. Para isolamento verdadeiro multi-tenant, combine `ulimit` com controladores de recursos cgroups v2, e considere isolamento de namespace (namespaces de utilizador, namespaces PID) para limites de segurança mais fortes. Na infraestrutura gerida, estes controlos são tipicamente dispostos em camadas ao nível do hipervisor e do runtime de contentores.

15%

Poupe 15% em todos os serviços

Teste as suas habilidades e obtenha Desconto em qualquer plano

Utilizar o código:

Skills
Começar a trabalhar