activando e desactivando um serviço de sistema em Python usando o DBus

O próximo picockpit-cliente reage a eventos de exclusão do frontend desactivando o seu serviço (a aplicação permanecerá instalada, no entanto).

Da mesma forma, quando decidir executar novamente a ligação picockpit-cliente, o serviço será reactivado e iniciado automaticamente para si.

Isto é possível usando o Interface Python DBus.

o DBus é um sistema de barramento para interagir com outras aplicações. As aplicações & serviços de sistema publicam uma certa interface sobre o DBus, que você pode usar.

Aqui está como fazer isso:

desactivar um serviço:

autocarro de importação

system_bus = dbus.SystemBus()
systemd1 = system_bus.get_object('org.freedesktop.systemd1', '/org/freedesktop/systemd1')
manager = dbus.Interface(systemd1, 'org.freedesktop.systemd1.Manager')
manager.DisableUnitFiles(['picockpit-client.service'], Falso)

manager.Reload()

imagem

Nós abrimos o SystemBus - há também um SessionBus ( dbus.SessionBus() ) que é usado para interagir com uma sessão do usuário. Neste caso queremos aceder aos serviços do Sistema, no entanto.

até gerir estas são chamadas "standard" - para aceder ao sistema é necessário passar por elas.

a próxima linha é onde instruímos o gerente a DesabilitarUnitFiles. Aqui estão mais algumas notas sobre isso:

  • a primeira variável é um array de strings - mesmo que você queira desativar apenas um serviço, você o passa como um array.
  • você passa em nome do seu serviço incluindo a parte '.service' - por exemplo picockpit-client.service
  • a segunda variável é necessária e seria Falsa para desativar para cada boot (e Verdadeiro para desativar apenas para este tempo de execução)

Aqui está a assinatura para DisableUnitFiles de a documentação oficial do DBus / systemd / Freedesktop.org:

imagem

Note que é importante fornecer todas as variáveis ao interagir com a interface DBus! Eles são não opcional e "definido para padrões sãos", como você pode ser usado a partir de muitas outras interfaces / APIs.

Finalmente, li online que as mudanças precisam de ser cometidas usando manager.Reload() (a documentação diz: Reload() pode ser invocado para recarregar todos os arquivos de unidade)

habilitar e iniciar um serviço:

autocarro de importação

system_bus = dbus.SystemBus()
systemd1 = system_bus.get_object('org.freedesktop.systemd1', '/org/freedesktop/systemd1')
manager = dbus.Interface(systemd1, 'org.freedesktop.systemd1.Manager')
manager.EnableUnitFiles(['picockpit-client.service'], Falso, Verdadeiro)
manager.Reload()
trabalho = gerente.RestartUnit('picockpit-client.service', 'fail')

imagem

Similar ao anterior, com a seguinte diferença para EnableUnitFiles:

  • há duas variáveis booleanas após o array de strings que precisam ser passadas em
  • a primeira variável booleana, como acima, determina se o serviço deve ser habilitado apenas para este tempo de execução (True) ou geralmente (False);
  • a segunda variável booleana é, de certa forma, descrita de forma críptica: "A segunda controla se as ligações simbólicas que apontam para outras unidades devem ser substituídas, se necessário." Eu decidi defini-la como True.

Aqui está a assinatura da EnableUnitFiles a partir da documentação:

imagem

Olhando para ele, minha escolha de "Verdadeiro" pode possivelmente não ser sensata para outras aplicações ("força" implica uma espécie de sobreposição de segurança).

Finalmente, RestartUnit para realmente começar o serviço:

  • note que isto requer um valor de string, não um conjunto de strings
  • o segundo valor é uma string que especifica o modo. Por favor, consulte a página documentação oficial para os diferentes modos que são possíveis.

Aqui está a assinatura da RestartUnit:

imagem

Nota: Eu não lido com os valores de retorno, idealmente e especialmente para aplicações críticas, você gostaria de olhar para isso - consulte o documentação oficial.

Erros

Descoordenação de assinaturas

ERRO:dbus.connection:Incapaz de definir argumentos (['picockpit-client.service'],) de acordo com a assinatura 'asb': : Mais itens encontrados na assinatura D-Bus do que nos argumentos Python

Se você receber um erro como o acima, verifique se você está passando todos os parâmetros, conforme exigido pela assinatura na documentação.

Neste caso, eu tinha (errado):

manager.DisableUnitFiles(['picockpit-client.service'])

em vez do correcto:

manager.DisableUnitFiles(['picockpit-client.service'], Falso)

Certifique-se também de verificar se você está passando em um fio (s), onde um conjunto de cordas (como) é necessário.


Ref