O CentOS 7 inicializa muito rápido e a rede não está pronta ao executar scripts cron

9

Acabei de atualizar do CentOS 6.5 para 7.0 e não estou muito feliz porque o novo systemdprovavelmente está me causando problemas. Parece que está simplesmente inicializando muito rápido, iniciando processos de forma assíncrona e danificando as dependências de serviço.

Por exemplo, tenho alguns scripts de configuração nos crondquais são acionados após uma reinicialização:

@reboot    /root/scripts/check_gmail.sh
@reboot    /root/scripts/start_gps_listener.sh

Isso resulta em todos os tipos de erros estranhos (mostrando apenas um deles):

Warning: stream_socket_client(): unable to connect to tcp://192.168.20.4:4001 
  (Network is unreachable) in /root/scripts/check_gmail.php on line 137
  ERROR: Network is unreachable (101)

Acima, estou escrevendo em um soquete TCP. É bastante claro para mim que crondé iniciado antes da rede ser inicializada corretamente como o network is unreachable.

O mesmo acontece com o Apache e o MySQL (MariaDB). O MySQL é bastante lento para iniciar (muitos dados), o que significa que o Apache e muitos dos meus crondscripts de inicialização estão falhando, pois o banco de dados MySQL não está sendo executado quando os scripts estão sendo chamados.

Eu tentei configurar dependências, mas sem sorte; Anexei networke mysqlserviços para [Unit](como visto com systemctl list-dependencies). Idealmente, todos os serviços esperam até que o MySQL esteja em funcionamento:

vi /lib/systemd/system/httpd.service
  [Unit]
  Description=The Apache HTTP Server
  After=network.target remote-fs.target nss-lookup.target network.service mysql.service

vi /lib/systemd/system/crond.service
  [Unit]
  Description=Command Scheduler
  After=syslog.target auditd.service systemd-user-sessions.service time-sync.target network.service mysql.service

Ao inicializar com o descrito acima, recebo os mesmos erros. Também recebo os emails, mailqpois a rede / DNS não está pronta ao processar scripts cron. Alguns minutos após a inicialização, eles são enviados corretamente.

Alguém pode ajudar a acertar isso certificando-se de que os serviços sejam disparados na ordem correta? Parece muito errado que ele seja inicializado tão rapidamente e, idealmente, foi feito da maneira antiga ", lançando um serviço ... espere ... inicie um novo serviço ... espere ... e assim por diante).

Observe que não tenho certeza se systemdesse é o meu problema - é apenas minha teoria do que posso ler da rede.

DHS
fonte
Você poderia postar a saída de grep -i concurrency /etc/default/rcS? Eu posso estar misturando meus sistemas init, mas me lembro que controla se os processos esperam um pelo outro terminar.
terdon
Não tenho arquivos com/etc/default/rc*
DHS
Desculpe, não sei onde estaria o equivalente do CentOS. Eu estava pensando no que é descrito aqui para o Debian, o que faz com que os serviços iniciem em paralelo. Pode haver algo parecido no seu caso.
terdon
2
Tente adicionar Requires=network.targetàs unidades acima.
casey
Ainda o mesmo problema depois de inserido Requires=network.targetem/lib/systemd/system/crond.service
DHS

Respostas:

9

Depois de muito mais leitura, encontrei a solução que funciona para mim.

Li este guia, Executando serviços depois que a rede estiver ativa . Uma pequena citação do guia:

Isso garantirá que todos os dispositivos de rede configurados estejam ativos e tenham um endereço IP atribuído antes que a inicialização continue.

Isso é exatamente o que eu queria, então ativei esse serviço e configurei a regra de dependência no arquivo de serviço para crond:

[root@srv]# systemctl enable NetworkManager-wait-online

[root@srv]# vi /lib/systemd/system/crond.service
  Requires=network.target
  After=syslog.target auditd.service systemd-user-sessions.service time-sync.target network.target mysqld.service

Como mysqldainda é baseado no antigo que init.deu precisava para criar um systemdserviço, conforme sugerido aqui, o systemctl enable difere do systemctl start :

[root@srv]# vi /lib/systemd/system/mysqld.service
  [Unit]
  Description=MySQL Server
  After=network.target
  [Service]
  Type=forking
  ExecStart=/etc/rc.d/init.d/mysql start
  ExecStop=/etc/rc.d/init.d/mysql stop
  [Install]
  WantedBy=multi-user.target

[root@srv]# systemctl daemon-reload
[root@srv]# chkconfig mysql off
[root@srv]# systemctl enable mysqld

E, finalmente, configure o serviço Apache para iniciar após o MySQL:

[root@srv]# vi /lib/systemd/system/httpd.service
  Requires=mysqld.service
  After=network.target remote-fs.target nss-lookup.target mysqld.service

Isso funciona para mim, pelo menos.

Eu usei esses comandos para verificá-lo posteriormente, onde eu posso ver claramente que a rede foi iniciada antes de pelo menos o MySQL e o Apache. Embora eu não consiga ver o crondlugar, mas posso ver que está funcionando nos meus scripts:

[root@srv]# systemd-analyze critical-chain
  multi-user.target @10.510s
    + httpd.service @10.344s +165ms
      + mysqld.service @9.277s +1.065s
        + network.target @9.273s
          + network.service @8.917s +355ms
            + iptables.service @444ms +157ms
              + basic.target @443ms
                [CUT]

Alguns outros comandos úteis que usei são:

# See exactly what takes how long (who to blame for the delay)
[root@srv]# systemd-analyze blame

# Check available names that can be used in the service files
[root@srv]# systemctl list-unit-files

Se alguém puder ver uma maneira melhor de fazer isso, compartilhe.

DHS
fonte
+1 para postar os comandos que você usou para depurar isso. Eu era capaz de resolver um nó realmente desagradável de problemas systemd-analyze critical-chain. Não apenas vou usá-lo com frequência, mas de repente sou vendido systemd. Obrigado!
Brian Topping
Você não deve modificar os arquivos de serviços gerenciados pelo seu gerenciador de pacotes de distribuição. Em vez disso, é melhor usar os arquivos de configuração drop-in. Veja a resposta em Como substituir ou configurar serviços systemd?
Ludovic Ronsin