Estou escrevendo um arquivo de unidade systemd para o OSSEC HIDS. O problema é que, quando o systemd inicia o serviço, ele imediatamente os interrompe.
Quando eu uso essa diretiva ExecStart, tudo funciona bem.
ExecStart=/var/ossec/bin/ossec-control start
Porém, quando faço pequenas melhorias, fico bem nos logs do OSSEC, que recebem o SIG 15 após o início.
ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start'
Se eu fizer outro pequeno serviço de troca, receberá SIG 15 após 20 segundos.
ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start && sleep 20'
Então, eu acho que esse systemd mata / bin / sh após o início do serviço e bin / sh mata o OSSEC.
Como posso resolver este problema?
Respostas:
incompatibilidade de protocolo de prontidão
Como Wieland sugeriu,
Type
o serviço é importante. Essa configuração indica qual protocolo de prontidão o systemd espera que o serviço fale.simple
Presume-se que um serviço esteja imediatamente pronto. Umforking
serviço é levado para ficar pronto depois que seu processo inicial bifurca uma criança e sai. Umdbus
serviço é considerado pronto quando um servidor aparece no Desktop Bus. E assim por diante.Se você não conseguir que o protocolo de prontidão declarado na unidade de serviço corresponda ao que o serviço faz, as coisas darão errado. As incompatibilidades do protocolo de prontidão fazem com que os serviços não iniciem corretamente ou (geralmente) sejam diagnosticados incorretamente pelo systemd como falhas. Quando um serviço é visto como falhando ao iniciar o systemd, garante que todo processo adicional órfão do serviço que pode ter sido deixado em execução como parte da falha (do ponto de vista dele) seja eliminado, a fim de trazer o serviço corretamente de volta ao inativo Estado.
Você está fazendo exatamente isso.
Primeiro de tudo, as coisas simples:
sh -c
não correspondemType=simple
ouType=forking
.No
simple
protocolo, o processo inicial é levado para ser o processo de serviço. Mas, de fato, umsh -c
wrapper executa o programa de serviço real como um processo filho . EntãoMAINPID
dá errado eExecReload
para de funcionar, para começar. Ao usarType=simple
, é preciso usarsh -c 'exec …'
ou não usarsh -c
em primeiro lugar. Este último é mais frequentemente o curso correto do que algumas pessoas pensam.sh -c
também não correspondeType=forking
. O protocolo de prontidão para umforking
serviço é bastante específico. O processo inicial precisa bifurcar um filho e sair. O systemd aplica um tempo limite a este protocolo. Se o processo inicial não bifurcar dentro do tempo alocado, é uma falha para ficar pronto. Se o processo inicial não sair dentro do tempo alocado, isso também será uma falha.o horror desnecessário que é
ossec-control
O que nos leva a coisas complexas: esse
ossec-control
script.Acontece que é um
rc
script do System 5 que executa entre 4 e 10 processos, que por sua vez bifurcam e saem também. É um daquelesrc
scripts do Sistema 5 que tenta gerenciar todo um conjunto de processos do servidor em um único script, comfor
loops, condições de corrida,sleep
s arbitrários para tentar evitá-los, modos de falha que podem sufocar o sistema em um estado semi-iniciado, e todos os outros horrores que levaram as pessoas a inventar coisas como o AIX System Resource Controller e daemontools duas décadas atrás. E não vamos esquecer o script de shell oculto em um diretório binário que ele reescreve em tempo real, para implementar idiossincráticosenable
edisable
verbos.Então, quando você o
/bin/sh -c '/var/ossec/bin/ossec-control start'
que acontece é o seguinte:ossec-control
.ossec-control
saídas.forking
nem osimple
protocolo de prontidão, systemd considera o serviço como um todo para falharam e fecha-lo de volta para baixo.Nada desse horror é realmente necessário no systemd. Nada disso.
uma unidade de serviço de modelo systemd
Em vez disso, escreve-se uma unidade de modelo muito simples :
Salve isso como
/etc/systemd/system/[email protected]
.Os vários serviços reais são instanciações deste modelo, denominadas:
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
A função habilitar e desabilitar vem diretamente do sistema de gerenciamento de serviços (com o bug 752774 do RedHat corrigido), sem a necessidade de scripts shell ocultos.
Além disso, o systemd conhece e rastreia cada serviço real diretamente. Ele pode filtrar seus logs com
journalctl -u
. Ele pode saber quando um serviço individual falhou. Ele sabe quais serviços devem estar habilitados e em execução.A propósito:
Type=simple
e a-f
opção é tão aqui quanto em muitos outros casos. Muito poucos serviços na natureza realmente sinalizam sua prontidão pela força doexit
, e esses aqui também não são esses casos. Mas é isso que oforking
tipo significa. Serviços na natureza, principalmente, apenas bifurcam e saem por causa de alguma noção errônea de sabedoria recebida de que é isso que os daemons devem fazer. De fato, não é. Não é desde a década de 1990. É hora de recuperar o atraso.Leitura adicional
fonte
Requires=
todas as instâncias necessárias e, em seguida, definidoPartOf=ossec.target
em ossec @ .service. Isso permitirá iniciar e parar o ossec iniciando e parando o ossec.target.Mantenha Type = bifurcação e forneça um local para o arquivo pid se o serviço / aplicativo de inicialização estiver mantendo algum pid.
[Unidade]
Descrição = "Executar aplicativo na inicialização"
Depois = network.target syslog.target auditd.service
[Serviço]
Tipo = bifurcar
PIDFile = / var / run / apache2 / apache2 / apache2.pid
ExecStart = / etc / init.d / apache2 inicie
ExecStop = / etc / init.d / apache2 stop
StandardOutput = syslog
StandardError = syslog
Reinicie = em falha
SyslogIdentifier = webappslog
[Instalação]
WantedBy = multiusuário.target
Alias = webapps
fonte
De certa forma, eu tinha um serviço systemd que parecia que o systemd o "mataria" depois dos 30 anos.
systemctl status service-name
apareceriamain process exited, code=exited, status=1/FAILURE
depois dos 30 anos.Ele funcionaria bem "isoladamente" (como manualmente no terminal com o mesmo ambiente ).
Acontece que era
dentro
my_script_to_spawn_process.sh
dele estava fazendo/bin/something > /dev/null 2>&1 &
que funciona, mas estava descartando as informações do log de saída (normalmente ele vai para um arquivo ou, se não for esse, possivelmente
journalctl
).Alterando-o para logar em outro lugar como
/bin/something > /tmp/my_file
depois, seguindo a
/tmp/my_file
revelada causa real. Que era (tangencialmente) que você não pode usar a sintaxeEnvironment=ABC="true"
como no bash, não deve haver aspas ou o valor-chave dentro de aspas como oEnvironment="ABC=true"
que estava fazendo com que meu processo fosse encerrado "em sua fase de configuração" após cerca de 30 anos.fonte
Observe que o modelo de daemon do systemd é simplista e incompatível com muitos daemons existentes que realizam múltiplas operações de forquilha, execução e configuração. Os mais comuns são os daemons que iniciam como raiz para configurar as coisas e depois mudam para um UID menos privilegiado para operação de rotina. Por exemplo, a inicialização do arquivo Pid é uma coisa que falha no systemd devido a problemas de privilégio. Existem soluções alternativas (não correções), mas estão mal documentadas.
A explicação do JdeBP é bem-vinda, mas incompleta, e sua afirmação de que tudo é culpa do ossec-control simplesmente não é verdadeira. Mesmo coisas bastante triviais são problemáticas, por exemplo, obter linhas de log não truncadas para depurar problemas ou mensagens de erro significativas do próprio systemd quando ele mata processos.
fonte