Existe uma maneira de esperar que a inicialização seja concluída [fechada]

4

Com systemd , pode-se consultar se a inicialização foi concluída pelo comando

systemctl is-system-running

que retorna o código de erro se a inicialização não foi concluída. Se alguém quiser esperar que a inicialização seja concluída, é claro que é possível executar novamente o comando até que ele retorne 0 .

Eu acho que "deve haver uma maneira melhor" de fazer isso. Existe um método que não depende de pesquisa?

O motivo pelo qual quero fazer isso é que atualmente tenho um script que baixa o firmware para um dispositivo que é reinicializado e deseja monitorá-lo para ver se ele é inicializado corretamente. Eu faço isso atualmente emitindo systemctl is-system-running via SSH até que ele retorne 0 ou não dentro do tempo que a inicialização deveria ter sido concluída. Claro que eu quero que isso termine o mais rápido possível.

    
por skyking 03.08.2018 / 15:01

2 respostas

1

Aguardando arquivo de unidade

Aqui está um protótipo que faz o que você está procurando. Para começar, aqui está um arquivo de unidade do systemd, waity.service :

$ cat /etc/systemd/system/waity.service
[Unit]
Description=Waity Service
After=systend-user-sessions.service

[Service]
Type=simple
ExecStart=/opt/bin/waity.sh

Script de espera

Ele executa um script que faz a interrogação do systemd para ver se ele está pronto para iniciar:

$ cat /opt/bin/waity.sh
#!/bin/bash

while $(sleep 10); do
  echo "waiting for systemd to finish booting..."
  if systemctl is-system-running | grep -qE "running|degraded"; then
    break
  fi
done

echo "systemd finished booting..."
echo "...do something else..."

Exemplo de execução

Agora ative este serviço:

$ systemctl enable --now waity.service

Agora, quando iniciarmos nosso sistema, esse serviço ficará em um loop de 10 segundos até ver que a ação is-system-running de systemctl retornará um estado running ou degraded . Qualquer uma dessas é uma indicação de que o sistema concluiu a inicialização.

O status deste serviço:

$ systemctl status waity.service
● waity.service - Waity Service
   Loaded: loaded (/etc/systemd/system/waity.service; static; vendor preset: disabled)
   Active: inactive (dead)

Aug 03 22:06:01 centos7 waity.sh[4519]: Got unexpected auxiliary data with level=1 and type=2
Aug 03 22:06:01 centos7 waity.sh[4519]: Got unexpected auxiliary data with level=1 and type=2
Aug 03 22:06:01 centos7 waity.sh[4519]: systemd finished booting...
Aug 03 22:06:01 centos7 waity.sh[4519]: ...do something else...
Aug 03 22:06:01 centos7 systemd[1]: Child 4519 belongs to waity.service
Aug 03 22:06:01 centos7 systemd[1]: waity.service: main process exited, code=exited, status=0/SUCCESS
Aug 03 22:06:01 centos7 systemd[1]: waity.service changed running -> dead
Aug 03 22:06:01 centos7 systemd[1]: waity.service: cgroup is empty
Aug 03 22:06:01 centos7 systemd[1]: Collecting waity.service
Aug 03 22:07:17 centos7 systemd[1]: Collecting waity.service

Podemos ver nas mensagens acima que detectamos uma inicialização concluída:

Aug 03 22:06:01 centos7 waity.sh[4519]: systemd finished booting...
Aug 03 22:06:01 centos7 waity.sh[4519]: ...do something else...

Nesse momento, poderíamos fazer o ...do something else... . Quando tudo isso estiver completo, este serviço irá para um estado concluído / morto.

    
por 04.08.2018 / 04:10
1

É possível esperar por esta condição sem consultar este comando em um loop, mas infelizmente não é tão simples ...

O systemd publicará um sinal StartupFinished no D-Bus assim que o boot for completo, por isso é possível assistir a isso e receber uma notificação.

Aqui está uma ferramenta simples dbus-wait que pode procurar sinais no D-Bus .

Consegui esperar até que a inicialização fosse concluída usando este comando:

dbus-wait org.freedesktop.systemd1.Manager StartupFinished

O problema com essa abordagem é que há uma condição de corrida lá. Se primeiro eu verificar se o sistema está rodando (com systemctl is-system-running ) e ver que ele ainda está "iniciando" e então decidir esperar pelo sinal, é possível que no momento dbus-wait irá se conectar ao barramento e começar a esperar o sinal, esse systemd acabou de inicializar e já postou esse sinal no barramento, o que fará com que dbus-wait espere por um evento que não vai acontecer e eventualmente expirará ...

Por outro lado, deve ser possível implementá-lo de maneira livre de condições de corrida, registrando primeiro o relógio para o evento, depois verificando a propriedade e, se ainda não estiver definido como "em execução", execute o loop de eventos para aguardar o sinal.

Eu implementei a abordagem acima e a propus ao upstream do systemd. Minha sugestão é permitir a execução de systemctl is-system-running --wait para essa finalidade (mas é possível que isso acabe fazendo com systemd com uma sintaxe diferente, possivelmente um comando separado). A proposta para o novo recurso systemd pode ser encontrada em PR # 9796 no projeto systemd. (Atualizarei esta resposta assim que for aceita e mesclada.)

UPDATE : o PR # 9796 foi fundido no systemd, começando com systemd v240, será possível aguardar até que a inicialização seja concluída com o seguinte comando:

systemctl is-system-running --wait
    
por 04.08.2018 / 08:24