Estou tentando fazer com que o systemd inicie um daemon e passe 8.192 soquetes de escuta. Eu tenho um arquivo .service
e .socket
que funciona de maneira confiável com um número mais "normal" de soquetes de escuta, assim:
# a-daemon.socket
[Unit]
Description=A Daemon (sockets)
After=network.target
[Socket]
Accept=no
ListenStream=8192
# a-daemon.service
[Unit]
Description=A Daemon
After=network.target
Requires=a-daemon.socket
[Install]
WantedBy=multi-user.target
[Service]
Type=notify
ExecStart=/usr/local/sbin/a-daemon
Mas se eu trocar a-daemon.socket
por uma versão com 8.192 ListenStream
linhas, uma para cada porta TCP de 8192 a 16383 inclusive, o daemon não iniciará mais. A unidade de soquete pode ser iniciada sem problemas, mas a unidade de serviço falha; a única mensagem de erro que recebo é
systemd[17563]: a-daemon.service: Failed to execute command: Argument list too long
systemd[17563]: a-daemon.service: Failed at step EXEC spawning /usr/local/sbin/a-daemon: Argument list too long
Pelo que entendi, isso não pode ser realmente um problema com a lista de argumentos , porque o systemd não coloca os números do soquete fd na linha de comando do daemon ou algo assim. Eu imaginei que era um problema com um limite no número de arquivos abertos simultâneos, então eu configurei DefaultLimitNOFILE=32768
e /etc/systemd/system.conf
uma configuração equivalente /etc/security/limits.conf
e reiniciei. Nenhuma mudança. Em seguida, coloquei ExecStartPre=/usr/sbin/prlimit -n
o arquivo .service e tentei reiniciá-lo, o que confirmou que o limite aumentado havia entrado em vigor:
prlimit[18134]: RESOURCE DESCRIPTION SOFT HARD UNITS
prlimit[18134]: NOFILE max number of open files 32768 32768 files
Mas o serviço ainda falha, da mesma forma. E agora estou sem ideias. Você pode sugerir algo que eu poderia tentar fazer para que isso funcione?
(Estou ciente de que ouvir em 8.192 portas TCP consecutivas é uma coisa estranha de se fazer. Por favor, aceite minha palavra de que tenho um bom motivo que não posso compartilhar.)
Ao olhar um pouco mais para as manpages do systemd, percebi que existe algo que o systemd coloca na
argv
área cujo tamanho é proporcional ao número de sockets de escuta:(negrito - ênfase minha) O que isso significa é que, se você tiver 8192
ListenStream
entradas em um arquivo de unidade de soquete, o systemd tentará colocarLISTEN_FDNAMES=[name]:[name]:...
, com 8192 repetições, ondename
está aFileDescriptorName
configuração, no ambiente para o serviço.FileDescriptorName
o padrão é o nome base completo do arquivo de unidade de soquete. Isso pode facilmente ultrapassar o limite fixo bastante baixo do Linux no comprimento de uma única variável de ambiente nome + valor (MAX_ARG_STRLEN
, geralmente 128k) e, portanto, causarexecve(2)
falha comE2BIG
.Para um daemon que não liga para os nomes, a cura é colocar
no arquivo de serviço (
[Service]
seção). Isso elimina a variável de ambiente problemática e deixa o kernel feliz.Não sei o que você faz se realmente precisar dos nomes fd para algo e atingir esse limite.