Para ver tudo:
 sudo prlimit --pid 2040
RESOURCE   DESCRIPTION                                  SOFT       HARD UNITS
AS         limite de espaço de endereços           ilimitado  ilimitado bytes
CORE       tamanho máximo de arquivo do núcleo             0  ilimitado bytes
CPU        Tempo da CPU                            ilimitado  ilimitado segundos
DATA       tamanho máximo de dados                 ilimitado  ilimitado bytes
FSIZE      tamanho máximo de arquivo               ilimitado  ilimitado bytes
LOCKS      número máximo de travas de arquivo man  ilimitado  ilimitado travas
MEMLOCK    espaço máximo de endereço travado na m 4161884160 4161884160 bytes
MSGQUEUE   máximo de bytes nos módulos POSIX          819200     819200 bytes
NICE       prioridade máxima de nice permitida             0          0 
NOFILE     número máximo de arquivos abertos            1024    1048576 arquivos
NPROC      número máximo de processos                 126639     126639 processo
RSS        tamanho máximo de conjunto residente    ilimitado  ilimitado bytes
RTPRIO     prioridade máxima de tempo real                 0          0 
RTTIME     tempo limite para tarefas em tempo rea  ilimitado  ilimitado microsse
SIGPENDING número máximo de sinais pendentes          126639     126639 sinais
STACK      tamanho máximo da pilha                   8388608  ilimitado bytes
 
Na saída do comando
$ lsof -p $(echo $$)
vemos os arquivos abertos pela sessão do shell. Repare na coluna FD (File Descriptors) os arquivos 0u, 1u e 2u.
São, respectivamente, os descritores de arquivo stdin, stdout e stderr.
Os descritores de arquivo não tem somente um número, também tem um nome, uma string.
 
Nessa imagem vemos a saída do comando
$ cat /proc/sys/fs/file-max
9223372036854775807
Isso é coisa do famigerado Systemd:
"Após discussões com o pessoal do Kernel um sistema com memcg realmente não deveria mais precisar de limites rígidos extras para descritores de arquivo já que eles são devidamente contabilizados pelo memcg de qualquer maneira. Portanto, vamos aumentar esses valores para seus valores máximos. Isso também adiciona uma opção em tempo de compilação para desativar isso para atender aos usuários que não desejam usar o memcg.
55
Os sysctls fs.nr_open e fs.file-max agora são automaticamente elevados para os valores mais altos possíveis, pois a contabilização separada de descritores de arquivo não é mais necessária porque o memcg já os rastreia corretamente como parte da contabilização de memória. Assim, dos quatro limites para descritores de arquivo atualmente aplicados (fs.file-max, fs.nr_open, RLIMIT_NOFILE hard, RLIMIT_NOFILE soft) desativamos os dois primeiros e mantemos apenas os dois últimos.
Um conjunto de opções em tempo de compilação (-Dbump-proc-sys-fs-file-max=no e -Dbump-proc-sys-fs-nr-open=no) foi adicionado para reverter essa mudança de comportamento, o que pode ser uma opção para sistemas que desativam o memcg no kernel.
1168
Vamos aumentar fs.file-max e fs.nr_open para seus respectivos máximos. Nos Kernels atuais um grande número de descritores de arquivo não representa mais um problema de desempenho e sua memória é rastreada adequadamente pelo memcg, contá-los e limitá-los em mais duas camadas de limites é desnecessário e apenas complica as coisas. Esta função, portanto, desativa 2 dos 4 níveis de limites para descritores de arquivo e torna RLIMIT_NOLIMIT (soft + hard) os únicos que realmente importam.
1199
Arg! O kernel impõe valores máximos e mínimos em fs.nr_open, mas não sabemos exatamente quais são. A expressão pela qual o máximo é determinado depende da arquitetura e é algo que não queremos copiar para o espaço do usuário, pois depende dos detalhes de implementação do kernel. Como o kernel não nos expõe o valor máximo, só nos resta tentar e torcer. Portanto, vamos começar com INT_MAX e, em seguida, reduzir o valor pela metade até encontrarmos um que funcione. Feio? Sim, com certeza, mas APIs do kernel são APIs do kernel, então o que podemos fazer..."
Confira aqui:
Veremos na prática.
- fs.file-max é o número máximo de descritores de arquivo que todo o sistema Linux pode ter aberto ao mesmo tempo.
- fs.nr_open é o número máximo de descritores de arquivo que um único processo pode abrir.
Foi esses dois que o Systemd liberou até o máximo delimitado pelo Kernel (unlimited, lembrando que 'unlimited' não significa um valor infinito).
 cat /proc/sys/fs/file-max
9223372036854775807
 cat /proc/sys/fs/nr_open
1048576
O máximo delimitado pelo Kernel é o valor que aparece ali nas saídas, então vemos que, de certa maneira, o Systemd está certo em liberar esse limites, pois o Kernel já os limita.
Isso inclui arquivos normais, sockets, pipes, etc.
- soft é o limite atual que um processo pode usar normalmente;
- hard é o limite máximo que o soft pode ser elevado (sem privilégios).
- O Soft limit pode ser alterado pelo próprio processo — até o valor de hard.
- O Hard limit só pode ser aumentado pelo root (ou com permissões elevadas - sudo, su, etc).
Contudo, agora entenderemos na prática.
O comando 
ulimit modifica limites de recursos do shell, até fechar o terminal.
 ulimit --help
- O parâmetro -S usa um limite 'soft' de recursos;
- O parâmetro -H usa um limite 'hard' de recursos;
- O parâmetro -u o número máximo de processos de usuário;
- O parametro -n o número máximo de descritores de arquivo abertos;
- O parâmetro -a todos os limites atuais são relatados
ulimit -S
unlimited
 ulimit -H
unlimited
 ulimit -u
29196
 ulimit -n
1024
Limite Soft:
 ulimit -Sn
1024
Limite Hard:
 ulimit -Hn
1048576
 ulimit -a
real-time non-blocking time  (microseconds, -R) unlimited
core file size              (blocks, -c) 0
data seg size               (kbytes, -d) unlimited
scheduling priority                 (-e) 0
file size                   (blocks, -f) unlimited
pending signals                     (-i) 29196
max locked memory           (kbytes, -l) 951984
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) 29196
virtual memory              (kbytes, -v) unlimited
file locks                          (-x) unlimited
Valores padrões no Kernel do Debian 12.
 uname -r
6.1.0-33-amd64
No arquivo do Systemd citado anteriormente vemos nas linhas 1187 e 1230, respectivamente:
r = sysctl_write("fs/file-max", t); e
r = sysctl_write("fs/nr_open", t);
onde vê-se que os valores aumentados até o máximo são aqueles constantes nos arquivos /proc/sys/fs/file-max e /proc/sys/fs/nr_open.
 cat /proc/sys/fs/file-max
9223372036854775807
 cat /proc/sys/fs/nr_open
1048576
Então os limites Soft e Hard ("...torna RLIMIT_NOLIMIT (soft + hard) os únicos que realmente importam...") são os que realmente importam: ulimit -Sn e ulimit -Hn.
Porém, vemos que a saída de 
'ulimit -Hn' é a mesma de 'cat /proc/sys/fs/nr_open': 1048576, sendo que -Hn é o limite Hard e nr_open é o número máximo de descritores de arquivo que um único processo pode abrir.
Testei em 4 máquinas com Debian 12 e as saídas padrões foram as mesmas.
O que se entende é que o limite Hard é o número máximo de descritores de arquivo que um único processo pode abrir. Um único processo pode abrir 1.048.576 descritores de arquivo.
O limite Soft é 1024, porém, o limite Soft não é exatamente um limite mínimo, o limite Soft é um valor inicial.
No caso, limite Soft só pode ser mudado até 1048576 (saída de ulimit -Hn), mais do que isso causará um erro, pois é tratado no Kernel.
Tente colocar um valor maior do que 1048576 (saída de ulimit -Hn):
 ulimit -n 1048576346
bash: ulimit: open files: impossível modificar limite: Operação não permitida
Como root:
# ulimit -n 10485761
-bash: ulimit: open files: impossível modificar limite: Operação não permitida
O limite Soft pode ser alterado para menos do que o limit de 1024:
# ulimit -n 10
# ulimit -Sn
10
 ulimit -n 2
 ulimit -Sn
2
Porém, como já foi dito isso vale só até fechar e abrir o terminal (Shell).
Depois o valor volta a 1024.
Acredito que o Systemd está certo porque se o próprio Kernel já limita os descritores de arquivo (unlimited não significa um valor infinito), não faz sentido limitar duas vezes os valores fs.nr_open e fs.file-max.
E atualmente os computadores trabalham com memória RAM generosa em relação à antigamente.
Essa limitação dos descritores de arquivo afetam somente máquinas muito antigas oque é natural, pois ninguém espera que um computador dure para sempre em relação a seu hardware.
Apesar de que os computadores de naves espaciais tem um hardware considerado obsoleto hoje e com pouca RAM, isso tem pouco a ver com descritores de arquivo, pois eles trabalham basicamente com cálculos.
Os descritores de arquivo são armazenados na memória RAM, a swappiness no disco (HD ou SD).
MODIFICANDO OS LIMITES
Execute:
 cat /proc/sys/fs/file-nr
Exemplo da saída:
11808	0	9223372036854775807
O primeiro número é o uso atual que mostra quantos descritores (ou identificadores) de arquivo estão atualmente alocados no sistema inteiro.
O segundo valor indica o número de descritores de arquivo alocados, mas não utilizados.
O terceiro número indica o número máximo de descritores de arquivo.
O Linux Kernel 2.6 e versões posteriores sempre relatam 0 como o número de descritores de arquivo livres — isso não é um erro, significa apenas que o número de descritores de arquivo alocados corresponde exatamente ao número de identificadores de arquivo utilizados.
Se o primeiro valor estiver perto do terceiro valor é hora de aumentar o número de descritores de arquivo.
1. Vendo o limite atual
 ulimit -Sn         # soft limit
1024
 ulimit -Hn        # hard limit
1048576
O limite Soft (inicial) padrão geralmente é o mesmo para as várias distribuições, o limite Hard (máximo) pode mudar.
2. Aumentar limite por processo (permanente)
 sudo vim /etc/security/limits.conf
Adicione essas linhas no final ou descomente:
*                soft    nofile          1048576
*                hard    nofile          1048576
O * aplica pra todos os usuários.
Pode trocar o * por um nome de usuário específico, caso quiser, por exemplo:
usuario soft    nofile          65536
usuario hard    nofile          1048576
*O valor a ser colocado depende da sua carga de trabalho.
Como já dito, caso for desktop/laptop de uso diário/cotidiano não precisa alterar nada.
Caso estiver usando PAM — geralmente sim -, Verifique se esses arquivos existem e têm a linha "session required pam_limits.so" habilitada:
 cat /etc/pam.d/common-session
 cat /etc/pam.d/common-session-noninteractive
Adicione (ou descomente) a linha neles:
session required pam_limits.so
Como já dito, caso for desktop/laptop de uso diário/cotidiano não precisa alterar nada.
3. Editar fs.nr_open e fs.file-max (limites do kernel)
Temporário:
 sudo sysctl -w fs.nr_open=65536
 sudo sysctl -w fs.file-max=1048576
 cat /proc/sys/fs/file-max
1048576
 cat /proc/sys/fs/nr_open
1048576
AVISO IMPORTANTE
Não coloque o parâmetro fs.nr_open no sysctl.conf com um valor menor do que a saída de cat 
/proc/sys/fs/nr_open.
Caso colocar um valor menor isso travará o Systemd na primeira reinicialização tendo que acessar com um sistema Live para comentar o parâmetro.
Teste primeiro colocando um valor maior do que a saída de cat /proc/sys/fs/nr_open e execute:
 sudo sysctl -p
Feche o terminal e tente abrir o terminal novamente, caso não abrir mais o terminal execute Ctrl+Alt+F1 ou F2 ou F3, etc (depende do sistema) que abrirá o login sem interface gráfica. Logue como root e comente o valor em fs.nr_open e execute 
sysctl -p e depois 
reboot:
Ctrl+Alt+F1
Logue como root.
# nano /etc/sysctl.conf
Comente o parâmetro.
Salve e saia.
# sysctl -p
# reboot
Aconselho a não mexer no parâmetro nr_open caso a saída deste já estiver num valor alto como 1048576 em relação à saída de ulimit -Sn.
Lembram que eu mencionei antes:
"Vejam bem, falei "difícil", não impossível, mas essa é uma outra discussão que não cabe agora no momento.
Veremos adiante que "malware" pode ser qualquer software que trava/prejudica o sistema, como a própria definição do limite nr_open, como veremos adiante na seção MODIFICANDO OS LIMITES > AVISO IMPORTANTE."
Permanente:
Adicione ao final do 
/etc/sysctl.conf:
fs.file-max=1048576
E depois aplique:
 sudo sysctl -p
O arquivo /etc/security/limits.conf só pode definir limites de recursos para usuários que efetuam login por meio do PAM; ele não afeta os limites de recursos dos serviços do sistema.
Portanto, quando sev inicia um serviço, por exemplo, com "sudo systemctl start servico" ou "sudo service servico start" este serviço não será afetado pelas limitações em /etc/security/limits.conf.
O número máximo de descritores de arquivo disponíveis para serviços de sistemas com Systemd é determinado pelo parâmetro DefaultLimitNOFILE no arquivo /etc/systemd/system.conf ou pelo parâmetro LimitNOFILE no arquivo /usr/lib/systemd/system/
.service.
O primeiro é uma configuração padrão global aplicada a todos os serviços do sistema enquanto que o último é um limite individual opcional para cada serviço. LimitNOFILE substituirá DefaultLimitNOFILE.
4. Se estiver usando Systemd temos duas maneiras de fazer: se quiser alterar os descritores para cada processo (programa, aplicativo, etc) com um valor específico, caso não, altere somente o arquivo /etc/systemd/system.conf.
4.1- Editar o arquivo ".service":
 sudo systemctl edit nome-do-servico
Acrescente na posição indicada:
[Service]
LimitNOFILE=1024:1048576
Salve e saia.

4.2- Altere o arquivo /etc/systemd/system.conf
Perceba que você pode alterar nesse arquivo os vários limites de Soft e Hard para cada serviço básico: CPU, MEMLOCK, etc.
Ou altere somente o DefaultLimitNOFILE=1024:1048576 que valerá como padrão para todos os serviços controlados pelo Systemd.
 sudo systemctl daemon-reload
 sudo systemctl restart nome-do-servico
Para o caso 4.2:
 sudo systemctl daemon-reexec
 sudo systemctl daemon-reload
5. Para verificar se um serviço ou processo está com o novo limite:
 cat /proc//limits
Ou, com lsof:
 lsof -p  | wc -l
Para ver o PID:
 pidof nome_processo
 pidof apache2
1020 1019 1018 1017 1016 1015
Ou
 top
ou
 htop
ou
 ps aux | grep nome_servico
 ps aux | grep java
kluster    37360  0.0  0.0   6352  2076 pts/0    S+   08:47   0:00 grep java
O PID é o primeiro número da linha, no caso: 37360.
 cat /proc/37360/limits
cat: /proc/37360/limits: Arquivo ou diretório inexistente
 lsof -p 37360 | wc -l
0
 
PID Pulseaudio: $ cat /proc/1298/limits
INFORMAÇÕES EXTRAS
Para verificar os limites de cada processo com um PID no diretório /proc:
 cat /proc//limits
Ou, com lsof:
 lsof -p  | wc -l
Para ver o PID:
 top
ou
 htop
ou
 ps aux | grep nome_servico
 ps aux | grep java
kluster    37360  0.0  0.0   6352  2076 pts/0    S+   08:47   0:00 grep java
O PID é o primeiro número da linha, no caso: 37360.
 cat /proc/37360/limits
cat: /proc/37360/limits: Arquivo ou diretório inexistente
 lsof -p 37360 | wc -l
0
Essas saídas significam que está ilimitado.
Nem todo processo cria um diretório PID dentro de /proc.
Exemplo:
 ps aux | grep pulseaudio
kluster     1298  0.0  0.3 842804 29244 ?        S<sl 07:49   0:00 /usr/bin/pulseaudio --daemonize=no --log-target=journal
kluster   121329  0.0  0.0   6352  2180 pts/0    S+   11:11   0:00 grep pulseaudio
Temos dois PIDs, daremos cat em cada um:
 cat /proc/121329/limits
cat: /proc/121329/limits: Arquivo ou diretório inexistente
 
$ cat /proc/1298/limits
Vemos que o PID do pulseaudio tem um diretório <PID> dentro de /proc, enquanto que o outro PID (que não é do pulseaudio, mas do grep) não criou um diretório em /proc, o que é óbvio, pois é um comando do shell e é temporário.
Podemos ver que cada coisa que se faz no Linux cria um PID e, no mínimo, um descritor de arquivo que são "apagados" depois de acordo com as suas atribuições.
 ps aux | grep pulseaudio
kluster     1298  0.0  0.3 842804 29244 ?        S<sl 07:49   0:00 /usr/bin/pulseaudio --daemonize=no --log-target=journal
kluster   131308  0.0  0.0   6352  2168 pts/0    S+   11:27   0:00 grep pulseaudio
Já foi criado um novo PID para o 'grep pulseaudio' enquanto que o PID do Pulseaudio permanece o mesmo.
Agora vamos entrar no diretório /proc:
 cd /proc
 ls
1       1358  16    26     46383  62693  8215       cgroups        locks
10      1364  160   262    46396  631    8219       cmdline        meminfo
10261   1367  161   2690   47     642    8227       consoles       misc
10271   1372  162   29     48     649    8235       cpuinfo        modules
102741  1386  163   291    4828   65     8487       crypto         mounts
Coloquei somente as 5 primeiras linhas.
Entrando num diretório PID:
 cd 1372
 ls
 
Entrando em um diretório /proc/pid.
 
Vendo o conteúdo do arquivo limits.
Vemos que a trama se complica, pois tem vários limites Soft e vários limites Hard.
Pode verificar também com:
 prlimit --pid  --nofile
Exemplo:
 prlimit --pid 1298 --nofile
RESOURCE DESCRIPTION                       SOFT HARD UNITS
NOFILE   número máximo de arquivos abertos  256  256 arquivos
PID Pulseaudio: 
 cat /proc/1298/limits