Serviços de usuário com systemd

Esse post é sobre como rodar serviços de usuário usando systemd. Utilizo o contexto de dar acesso local aos meus arquivos que estão no Mega como base.

Objetivo

Quero rodar o Mega pra manter meus aplicativos sincronizados. O problema é que ele adiciona repositórios novos no sistema para se atualizar. O que o Sr Debiano, fala sobre isso?

⚠️ Adding third-party repositories, or repositories from multiple versions of Debian, can break your system in ways that are hard to fix.

Fontes de Repositório Debian

Beleza! Vamos seguir! E como sempre, vamos fazer a coisa bem feita. Os objetivos são:

  • Isolado do sistema
  • Baixo gasto de recursos
  • Simples

Visão geral

A solução que estou montando desta vez é a seguinte.

  1. Criar contêiner Debian usando o Distrobox.
  2. Em geral, o Distrobox dá acesso a todo o seu diretório home para o contêiner, mas ele facilita dar acesso apenas a uma pasta interna do seu home.
  3. Instalar o MegaCMD no contêiner para sincronizar sem a necessidade de uma interface gráfica
  4. Colocar para iniciar automaticamente usando um serviço do systemd.

Observações

O Distrobox está rodando sobre Podman e seria possível fazer tudo funcionar sem a camada extra do Distrobox. Existem até mesmo umas soluções super elegantes usando a intregração do Podman com o systemd, mas estas soluções parecem mais complexas. Também simplifica bastante utilizar as facilidades que o Distrobox fornece, como por exemplo, passar o meu diretório home e integrar com o meu usuário.

Uma alternativa mais simples a usar o systemd consiste em inicializar o servidor do Mega pela interface gráfica usando o GNOME Tweaks. Em termo de simplicidade isso é melhor, o que é um ponto positivo para esta alternativa. Por outro lado, isso gera um terminal que preciso deixar aberto, usando o MegaCMD, ou um aplicativo intrusivo, se usar o Mega Desktop que pode ser exportado pelo Distrobox. Além do fato de que não há controle automatizado para falhas, política de uso de recursos e reinício automático que o systemd fornece.

Para colocar o MegaCMD para rodar, você começa rodando o comando de instalação fornecido. O restante segue o guia do usuário. Uma vez instalado, você precisa rodar o mega-login uma vez para fornecer os dados da sua conta. Os arquivos podem ser acessados pela sincronização local que é feita pelo mega-sync. Em teoria, poderia ser feito também pelo mega-fuse-add segundo o tutorial FUSE, mas isso só disponibiliza os arquivos dentro do contêiner e não fora dele que é o que eu quero.

Serviço

O systemd é um conjunto de componentes básicos para sistemas Linux que, dentre outras coisas, inicia e gerencia todos os outros serviços e processos do sistema. Além do modo principal, há um modo usuário, o systemd –user, onde cada usuário pode ter sua própria instância do systemd para gerenciar serviços e tarefas pessoais sem precisar de privilégios de administrador. O nosso objetivo é colocar o MegaCMD para rodar no modo usuário.

Para rodar um serviço systemd em modo usuário:

  1. Crie o arquivo de unidade .service em ~/.config/systemd/user/.
  2. Recarregue o systemd com systemctl --user daemon-reload.
  3. Habilite e inicie o serviço com systemctl --user enable --now <serviço>.

Arquivo de unidade do serviço

A primeira coisa a fazer é criar o arquivo de unidade, ou unit file, e colocar em alguma pasta que o systemd utiliza para buscar por esse tipo de arquivos para serviços de usuário. No caso, coloquei o seguinte arquivo em ~/.config/systemd/user/megasync.service.

[Unit]
Description=Servidor Mega rodando em distrobox Debian 13

[Service]
Type=simple
Slice=background.slice
ExecStart=/usr/bin/distrobox enter megasync --no-tty -- mega-cmd-server
ExecStartPost=/usr/bin/distrobox enter megasync --no-tty -- mega-log -c INFO
ExecReload=/usr/bin/distrobox enter megasync --no-tty -- mega-reload
ExecStop=/usr/bin/distrobox enter megasync --no-tty -- mega-quit
ExecStopPost=/usr/bin/distrobox stop megasync --yes
Restart=always

[Install]
WantedBy=default.target

A especificação desse tipo de arquivo depende dos arquivos de unidade e dos serviços e é bem complexo. A questão é que a maioria dos usos é razoavelmente simples, então vou descrever este uso específico. E então, o que essa porra faz?

Seção [Unit]

Além da descrição, é possível puxar outros serviços para rodarem também nesta seção. Este serviço não precisa de outros, então não é necessário colocar mais nada aqui. Mas a descrição de como esse processo funciona é importante para entender o systemd em geral e a seção [Install]. Tem muitas formas de puxar outros serviços, até mesmo garantindo que você só roda depois de outro iniciar, mas a forma mais simples é usando o Wants. Colocar uma linha de Wants na seção [Unit] faz com que outro serviço seja iniciado também e ambos continuam e podem falhar de forma independente. No final das contas, o systemd corresponde a ordenar os serviços do sistema e eles se ligam por dependências, tipo o que o Wants faz.

Seção [Install]

Esta seção serve para descrever quem chamará este serviço. O que a linha WantedBy=default.target faz é equivalente a adicionar uma linha de Wants=megasync.service na seção de [Unit] do default.target. Como o Wants faz com que ambos continuem de forma independente, adicionar esta linha lá não afeta nada rodar o default.target.

No caso, uma unidade do tipo target, ou alvo, serve para agrupar e sincronizar dependências entre unidades do systemd. Para serviços que não fazem parte da inicialização do sistema, eles devem ser instalados no alvo padrão, que pode ser obtido usando o seguinte comando.

systemctl --user get-default

Para listar todos os alvos disponíveis, você pode usar:

systemctl --user list-units --type=target

Seção [Service]

A maioria desta seção corresponde aos comandos que interagem com o serviço, como o ExecStart e ExecStartPost para iniciar, o ExecReload para recarregar, e o ExecStop e ExecStopPost para parar. No caso, o ExecStartPost roda depois do ExecStart e o ExecStopPost roda depois do ExecStop. O Restart indica que deve manter o serviço rodando e o Type é o tipo de serviço, que normalmente é simples. Esses não tem muito o que explicar.

O que é mais interessante é falar sobre o Slice. Uma unidade do tipo slice, ou fatia, serve para representar como administrar recursos computacionais de um conjunto de processos. Para processos de usuário em desktops, há uma recomendação de separar entre 3 fatias de recursos:

  • session.slice: processos essenciais para manter a sessão de usuário rodando
  • app.slice: o padrão para aplicativos ou serviços do usuário
  • background.slice: para tarefas que rodam em segundo plano e são não essenciais

Com essa separação, quando o sistema estiver sobrecarregado no uso de CPU ou memória, é possível dar prioridade aos processos mais importantes ou até mesmo desligar serviços não essenciais para manter a sessão do usuário rodando. Esse é um motivo bem importante para colocar um serviço para rodar pelo systemd. Assim, eu posso deixar claro que estou rodando um serviço não essencial e pode ser desligado se o computador estiver sobrecarregado.

A lista dos slices disponíveis pode ser obtido com o seguinte comando:

systemctl --user list-units --type=slice

Habilitando o serviço

Depois que o arquivo de unidade é colocado no local correto, é necessário primeiro indicar ao systemd de que foi realizada uma mudança nos arquivos de unidade e que ele deve procurar por novos serviços.

systemctl --user daemon-reload

Agora, é necessário habilitar o serviço para que ele seja instalado usando o que foi definido na seção [Install].

systemctl --user enable megasync.service

Como o default.target já foi iniciado, ele não irá iniciar o serviço pelo Wants que foi cadastrado. Mas quando a conta do usuário for reiniciada, o serviço vai rodar naturalmente. Para iniciar o serviço, basta rodar:

systemctl --user start megasync.service

A linha a seguir é uma abreviação para habilitar e iniciar o serviço.

systemctl --user enable --now megasync.service

O status do serviço pode ser obtido com

systemctl --user status megasync.service

Os logs do serviço podem ser obtidos com

journalctl --user -u megasync.service

No caso, o -u corresponde a indicar a unidade que queremos ver os logs.

Posts Similares

  • Como montei esta página?

    O domínio eu comprei no registro.br. O legal de páginas nom.br é que são muito baratas e muita…