O poder subestimado dos serviços do usuário
Originalmente publicado no vivaolinux.
Introdução
As pessoas não sabem o quanto serviços quem rodam a nível de usuário por parte do init system podem ser úteis no dia a dia. Por não saberem disso, elas delegam essa função aos WMs1 ou scripts de inicialização o que elimina as vantagens de se usar um init system para isso.
Problema
Quando você monta um sistema minimalista com um simples gestor de janelas, você mesmo é responsável por iniciar serviços que rodam em segundo plano a fim de usufruir de funcionalidades como:
- Áudio funcionando
- Barra de status
- Notificações
- Agente de SSH
- Papel de parede
- Serviços de IA
Você está ali montando a configuração do seu Window Manager favorito e de
repente se vê colocando vários comandos de inicialização.
-- ~/.config/hypr/hyprland.lua
hl.on("hyprland.start", function ()
hl.exec_cmd("hyprpaper")
hl.exec_cmd("pipewire")
hl.exec_cmd("wireplumber")
hl.exec_cmd("pipewire-pulse")
hl.exec_cmd("ssh-agent -D -a " .. os.getenv("XDG_RUNTIME_DIR").."/ssh-agent.sock")
hl.exec_cmd("ollama serve")
end)
O problema é que esses serviços não possuem nenhum tipo de monitoramento, os seus logs não ficam disponíveis pra você acessar e você não tem como saber se o serviço inicializou da forma correta ou não.
Solução
Eu penso que esse tipo de coisa deveria ser gerenciado pelo init system do
sistema operacional com serviços que rodam a nível de usuário. O systemd
suporta isso e o OpenRC também! Portanto, vou usar esses dois gestores para
exemplificar como solucionei esse problema.
Systemd
No systemd você pode criar serviços de usuário através de arquivos de unit localizados em:
~/.config/systemd/user/
Exemplo de serviço para o Wireplumber:
[Unit]
Description=Wireplumber daemon
After=pipewire.service
Requires=pipewire.service
[Service]
Type=forking
ExecStart=/usr/bin/wireplumber
Restart=on-failure
PIDFile=/home/user/.local/var/run/wireplumber.pid
[Install]
WantedBy=default.target
Para habilitar: systemctl --user enable wireplumber.service.
Note como o wireplumber depende de outros serviços para executar (pipewire). Tudo isso é gerenciado pelo systemd automaticamente.
OpenRC
No OpenRC, os scripts de usuário ficam em:
~/.config/rc/init.d/ (para configurações por usuário)
Exemplo de serviço para o Wireplumber:
#!/sbin/openrc-run
name="wireplumber"
description="Wireplumber daemon"
command="/usr/bin/wireplumber"
command_background="true"
supervisor="supervise-daemon"
pidfile="/home/user/.local/var/run/wireplumber.pid"
depend() {
need pipewire
}
Para habilitar: rc-update -U add wireplumber
O OpenRC também consegue iniciar serviços que dependem um do outro na ordem
correta igual o systemd faz! Porém, há um detalhe: no OpenRC você precisa criar
um runlevel específico para serviços de usuário, adicionar os serviços que
você quer e mudar para esse runlevel na hora do login.
Rode:
mkdir -p ~/.config/rc/runlevels/wayland
e então:
rc-update -U add wireplumber wayland
A única coisa que o teu gestor de janelas precisa fazer durante o login é mudar
o runlevel que o OpenRC se encarrega do resto.
-- /home/user/.config/hypr/hyprland.lua
hl.on("hyprland.start", function ()
hl.exec_cmd("/sbin/openrc -U wayland")
end)
Recursos
- Testado no Debian Forky com OpenRC
- Testado no NixOS com systemd
Conclusão
A única coisa que o gestor de janelas tem que se preocupar é com a configuração de teclas de atalho, o resto tem que ficar a cargo do sistema de init, pois não é papel do Hyprland ou qualquer outro WM gerenciar serviços em segundo plano e variáveis de ambiente. Os WMs são muito limitados nesse sentido, eles não guardam logs dos processos, quando o serviço para o WM não reinicializa, enfim, são muitas limitações que nem compensa delegar essa função a eles. Aproveita que você usa um init system moderno (systemd, OpenRC, runit e afins) e usufrua de um desktop minimalista sem deixar a sua configuração complicada.
Resultado final:
/home/user/.config/rc
├── conf.d
│ └── ollama-user.conf
├── init.d
│ ├── hyprpaper
│ ├── ollama-user
│ ├── pipewire
│ ├── pipewire-pulse
│ ├── ssh-agent
│ ├── waybar
│ └── wireplumber
├── rc.conf
└── runlevels
└── wayland
├── hyprpaper -> /home/user/.config/rc/init.d/hyprpaper
├── ollama-user -> /home/user/.config/rc/init.d/ollama-user
├── pipewire -> /home/user/.config/rc/init.d/pipewire
├── pipewire-pulse -> /home/user/.config/rc/init.d/pipewire-pulse
├── ssh-agent -> /home/user/.config/rc/init.d/ssh-agent
├── waybar -> /home/user/.config/rc/init.d/waybar
└── wireplumber -> /home/user/.config/rc/init.d/wireplumber
5 directories, 16 files
Quem quiser mais detalhes sobre algum serviço específico é só comentar. Forte abraço!
WM é uma sigla para Window Manager que significa “Gestor de janela” em português. ↩︎