GNU/Linux >> Linux Esercitazione >  >> Cent OS

Centos - Systemd uccide il servizio immediatamente dopo l'avvio?

Sto scrivendo systemd file unit per OSSEC HIDS. Il problema è che quando systemd avvia i servizi li interrompe immediatamente.

Quando utilizzo il seguente ExecStart direttiva funziona tutto bene.

ExecStart=/var/ossec/bin/ossec-control start

Ma quando faccio questo dopo un piccolo miglioramento, trovo nei registri OSSEC che riceve SIG 15 dopo l'inizio.

ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start'

Se apporto un'altra piccola modifica, il servizio riceverà SIG 15 dopo 20 secondi.

ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start && sleep 20'

Quindi, suppongo, quel systemd uccide /bin/sh processo dopo l'avvio del servizio e /bin/sh quindi uccide OSSEC .

Come posso risolvere questo problema?

Risposta accettata:

Mancata corrispondenza del protocollo di preparazione

Come suggerisce Wieland, il Type del servizio è importante. Questa impostazione indica quale protocollo di preparazione systemd si aspetta che il servizio parli. Un simple si presume che il servizio sia immediatamente pronto. Un forking il servizio viene considerato pronto dopo che il suo processo iniziale esegue il fork di un figlio e quindi esce. Un dbus il servizio viene considerato pronto quando un server viene visualizzato sul bus desktop. E così via.

Se non ottieni il protocollo di prontezza dichiarato nell'unità di servizio in modo che corrisponda a ciò che fa il servizio, le cose vanno storte. Le mancate corrispondenze del protocollo di disponibilità fanno sì che i servizi non vengano avviati correttamente o (più in genere) vengano diagnosticati (erroneamente) da systemd come guasti. Quando si ritiene che un servizio non si avvii systemd assicura che ogni processo aggiuntivo orfano del servizio che potrebbe essere stato lasciato in esecuzione come parte dell'errore (dal suo punto di vista) viene interrotto per riportare correttamente il servizio allo stato inattivo.

Stai facendo esattamente questo.

Prima di tutto, le cose semplici:sh -c non corrisponde a Type=simple o Type=forking .

Nel simple protocollo, il processo iniziale viene considerato essere il processo di servizio. Ma in effetti un sh -c wrapper esegue il programma di servizio effettivo come processo figlio . Quindi MAINPID va storto e ExecReload smette di funzionare, tanto per cominciare. Quando si utilizza Type=simple , è necessario utilizzare sh -c 'exec …' o non utilizzare sh -c innanzitutto. Quest'ultimo è più spesso il corso corretto di quanto alcune persone pensino.

sh -c non corrisponde a Type=forking o. Il protocollo di prontezza per un forking il servizio è abbastanza specifico. Il processo iniziale deve biforcare un figlio e quindi uscire. systemd applica un timeout a questo protocollo. Se il processo iniziale non si biforca entro il tempo assegnato, è un fallimento nel diventare pronto. Se il processo iniziale non termina entro il tempo assegnato, anche questo è un fallimento.

l'orrore non necessario che è ossec-control

Il che ci porta alle cose complesse:quel ossec-control copione.

Si scopre che è un rc di System 5 script che biforca tra 4 e 10 processi, che a loro volta si biforcano ed escono anch'essi. È uno di quei rc di System 5 script che tenta di gestire un intero set di processi server in un unico script, con for loop, condizioni di gara, sleep arbitrario s per cercare di evitarli, modalità di errore che possono soffocare il sistema in uno stato semi-avviato e tutti gli altri orrori che hanno portato le persone a inventare cose come AIX System Resource Controller e daemontools due decenni fa. E non dimentichiamo lo script di shell nascosto in una directory binaria che riscrive al volo, per implementare l'idiosincratico enable e disable verbi.

Correlati:Debian – Come scoprire come è stato installato un particolare pacchetto?

Quindi, quando /bin/sh -c '/var/ossec/bin/ossec-control start' quello che succede è che:

  1. systemd esegue il fork di quello che si aspetta essere il processo di servizio.
  2. Questa è la shell, che esegue il fork di ossec-control .
  3. Che a sua volta biforca tra 4 e 10 nipoti.
  4. I nipoti si biforcano ed escono a turno.
  5. I pronipoti si biforcano ed escono tutti in parallelo.
  6. ossec-control esce.
  7. La prima shell esce.
  8. I processi di servizio erano il bis-bis- nipoti, ma perché questo modo di lavorare non corrisponde a il forking il simple readiness protocol, systemd considera il servizio nel suo insieme non riuscito e lo chiude nuovamente.

Niente di tutto questo orrore è effettivamente necessario sotto systemd. Niente di tutto questo.

un'unità di servizio modello systemd

Invece, si scrive un'unità modello molto semplice :

[Unit]
Description=The OSSEC HIDS %i server
After=network.target 

[Service]
Type=simple
ExecStartPre=/usr/bin/env /var/ossec/bin/%p-%i -t
ExecStart=/usr/bin/env /var/ossec/bin/%p-%i -f

[Install]
WantedBy=multi-user.target

Salvalo come /etc/systemd/system/[email protected] .

I vari servizi effettivi sono istanziazioni di questo modello, denominato:

  • [email protected]
  • [email protected]
  • [email protected]
  • [email protected]
  • [email protected]
  • [email protected]
  • [email protected]
  • [email protected]
  • [email protected]
  • [email protected]
  • [email protected]

Quindi abilitare e disabilitare la funzione proviene direttamente dal sistema di gestione del servizio (con il bug di RedHat 752774 corretto), senza bisogno di script di shell nascosti.

 systemctl enable [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected]

Inoltre, systemd viene a conoscenza e traccia direttamente ogni servizio effettivo. Può filtrare i loro registri con journalctl -u . Può sapere quando un singolo servizio ha fallito. Sa quali servizi dovrebbero essere abilitati e in esecuzione.

A proposito:Type=simple e il -f opzione sono proprio qui come lo sono in molti altri casi. Pochissimi servizi in natura segnalano effettivamente la loro disponibilità a forza di exit , e anche questi qui non sono casi del genere. Ma questo è ciò che il forking tipo significa. I servizi in natura nella principale si biforcano ed escono a causa di un'idea errata ricevuta che è ciò che dovrebbero fare i daimon. In effetti, non lo è. Non è più dagli anni '90. È ora di recuperare il ritardo.

Ulteriori letture

  • Jonathan de Boyne Pollard (2015). Problemi di prontezza del protocollo con i demoni Unix . Risposte frequenti.

Cent OS
  1. CentOS / RHEL 7:impossibile avviare il servizio vsftpd

  2. CentOS / RHEL 7:impossibile avviare il servizio Samba

  3. systemd:SIGTERM subito dopo l'avvio

  4. Impossibile avviare il servizio postgresql su CentOS 7

  5. Impossibile avviare il servizio di rete CentOS 7

Come avviare il servizio all'avvio con RHEL 8 / CentOS 8 Linux

Come avviare, arrestare o riavviare i servizi in CentOS 8

Avvia automaticamente il servizio OpenCA tramite Systemd in CentOS 7

Il servizio Systemd non avvia Nodejs?

CentOS / RHEL 7:Abilita NTP per l'avvio all'avvio dopo una nuova installazione (disabilita chrony)

CentOS / RHEL 7:Guida per principianti alle unità di servizio systemd