
dbus
supostamente fornece "uma maneira simples para os aplicativos conversarem entre si".
Mas ainda não tenho certeza para que serve, na prática. Nunca vi uma situação em que dbus
fosse útil, só vejo avisos de que algum dbus
componente apresentou erros, como quando inicio o terminador na linha de comando (para poder ver os erros):
Error retrieving accessibility bus address: org.freedesktop.DBus.Error.ServiceUnknown: The name org.a11y.Bus was not provided by any .service files
Eu me livrei do erro acima adicionando NO_AT_BRIDGE=1
ao /etc/environment
. Não tenho ideia do que isso faz.
Quase todos os aplicativos GUI parecem estar vinculados ao dbus
. Alguns permitem ser iniciados sem dbus
, ou seja:
terminator --no-dbus
Não vejo diferença no comportamento. O que deveria parar de funcionar, quando terminator
é iniciado sem dbus
?
Além disso, tentei desabilitar vários componentes do dbus para ver o que para de funcionar:
Eu apaguei /etc/X11/Xsession.d/95dbus_update-activation-env
só para ver o que acontece. Ele continha o seguinte código:
if [ -n "$DBUS_SESSION_BUS_ADDRESS" ] && [ -x "/usr/bin/dbus-update-activation-environment" ]; then
# subshell so we can unset environment variables
(
# unset login-session-specifics
unset XDG_SEAT
unset XDG_SESSION_ID
unset XDG_VTNR
# tell dbus-daemon --session to put the Xsession's environment in activated services' environments
dbus-update-activation-environment --verbose --all
)
fi
Tudo funciona da mesma forma, pelo que posso dizer. Qual foi o propósito do script acima?
Em que situação seria útil que meus aplicativos se comunicassem via dbus
?
Existem aplicativos que não funcionam sem o dbus
?
Meu sistema é Debian Buster e estou usando um ambiente openbox simples (sem nenhum ambiente de desktop como Gnome ou KDE)
Responder1
dbus
faz exatamente o que você disse: permite a comunicação bidirecional entre aplicativos.
Para o seu exemplo específico que você mencionou terminator
. Depágina de manual do terminador, Nós vemos:
--new-tab If this is specified and Terminator is already running, DBus will be used to spawn a new tab in the first Terminator window.
Então, se você fizer isso de outro terminal (konsole, xterm, gnome-terminal):
$ terminator &
$ terminator --new-tab &
Você verá que o primeiro comando abre uma nova janela. O segundo comando abre uma nova aba na primeira janela. Isso é feito pelo segundo processo usando dbus para encontrar o primeiro processo, solicitando que ele abra uma nova guia e depois saia.
Se você fizer isso de outro terminal:
$ terminator --no-dbus &
$ terminator --new-tab &
Você verá que o primeiro comando abre uma nova janela. O segundo comando não consegue encontrar o dbus da primeira janela, então abre uma nova janela. Instalei o terminator para testar isso e é verdade.
Além disso, suspeito que o polkit seria afetado. Polkit usa dbus para elevar privilégios para aplicativos GUI. É como o sudo
mundo da GUI. Se você estiver no gnome e vir toda a tela coberta enquanto a senha do administrador for solicitada, isso é o polkit em ação. Suspeito que você não receberá esse prompt em nenhum aplicativo GUI iniciado, terminator
se tiver o --no-dbus
. Ele falhará na autenticação ou recorrerá a alguma autenticação de terminal. De terminator
tentar pkexec ls
. Isso será executado ls
com privilégios elevados. Veja se é diferente com e sem a --no-dbus
opção. Não tenho um agente polkit em meu gerenciador de janelas (i3), então não posso testar este.
Eu conheço principalmente o dbus em termos de systemd, então é daí que virá o resto da minha resposta.
Existem aplicativos que não funcionam sem o
dbus
?
Sim. Pegar systemctl
. systemctl status
emitirá uma consulta para "org.freedesktop.systemd1"
e apresentará isso a você. systemctl start
chamará um método dbus e passará a unidade como argumento para esse método. systemd
recebe a chamada e executa a ação.
Se você quiser agir em resposta à mudança de estado de uma unidade do systemd (ou seja, foo.service), poderá obter um descritor de arquivo para interface org.freedesktop.DBus.Properties
com path /org/freedesktop/systemd1/unit/foo_2eservice
e member PropertiesChanged
. Configure um inotify
nesse FD e de repente você terá uma maneira de reagir a um serviço iniciando, parando, falhando, etc.
Se você quiser dar uma olhada no que está disponível no systemd dbus para uma unidade específica (ou seja ssh.service
), tente este comando:
busctl introspect \
org.freedesktop.systemd1 \
/org/freedesktop/systemd1/unit/ssh_2eservice
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
org.freedesktop.DBus.Introspectable interface - - -
.Introspect method - s -
org.freedesktop.DBus.Peer interface - - -
.GetMachineId method - s -
.Ping method - - -
org.freedesktop.DBus.Properties interface - - -
.Get method ss v -
.GetAll method s a{sv} -
.Set method ssv - -
.PropertiesChanged signal sa{sv}as - -
org.freedesktop.systemd1.Service interface - - -
.AttachProcesses method sau - -
.GetProcesses method - a(sus) -
.AllowedCPUs property ay 0 -
.AllowedMemoryNodes property ay 0 -
.AmbientCapabilities property t 0 const
.AppArmorProfile property (bs) false "" const
.BindPaths property a(ssbt) 0 const
.BindReadOnlyPaths property a(ssbt) 0 const
.BlockIOAccounting property b false -
.BlockIODeviceWeight property a(st) 0 -
.BlockIOReadBandwidth property a(st) 0 -
.BlockIOWeight property t 18446744073709551615 -
.BlockIOWriteBandwidth property a(st) 0 -
.BusName property s "" const
.CPUAccounting property b false -
.CPUAffinity property ay 0 const
.CPUAffinityFromNUMA property b false const
.CPUQuotaPerSecUSec property t 18446744073709551615 -
.CPUQuotaPeriodUSec property t 18446744073709551615 -
.CPUSchedulingPolicy property i 0 const
.CPUSchedulingPriority property i 0 const
.CPUSchedulingResetOnFork property b false const
.CPUShares property t 18446744073709551615 -
.CPUUsageNSec property t 18446744073709551615 -
.CPUWeight property t 18446744073709551615 -
.CacheDirectory property as 0 const
.CacheDirectoryMode property u 493 const
.CapabilityBoundingSet property t 18446744073709551615 const
.CleanResult property s "success" emits-change
.ConfigurationDirectory property as 0 const
.ConfigurationDirectoryMode property u 493 const
.ControlGroup property s "/system.slice/ssh.service" -
.ControlPID property u 0 emits-change
.CoredumpFilter property t 51 const
.DefaultMemoryLow property t 0 -
.DefaultMemoryMin property t 0 -
.Delegate property b false -
.DelegateControllers property as 0 -
.DeviceAllow property a(ss) 0 -
.DevicePolicy property s "auto" -
.DisableControllers property as 0 -
.DynamicUser property b false const
.EffectiveCPUs property ay 0 -
.EffectiveMemoryNodes property ay 0 -
.Environment property as 0 const
.EnvironmentFiles property a(sb) 1 "/etc/default/ssh" true const
.ExecCondition property a(sasbttttuii) 0 emits-invalidation
.ExecConditionEx property a(sasasttttuii) 0 emits-invalidation
.ExecMainCode property i 0 emits-change
.ExecMainExitTimestamp property t 0 emits-change
.ExecMainExitTimestampMonotonic property t 0 emits-change
.ExecMainPID property u 835 emits-change
.ExecMainStartTimestamp property t 1597235861087584 emits-change
.ExecMainStartTimestampMonotonic property t 5386565 emits-change
.ExecMainStatus property i 0 emits-change
.ExecReload property a(sasbttttuii) 2 "/usr/sbin/sshd" 2 "/usr/sbin/sshd" "… emits-invalidation
.ExecReloadEx property a(sasasttttuii) 2 "/usr/sbin/sshd" 2 "/usr/sbin/sshd" "… emits-invalidation
.ExecStart property a(sasbttttuii) 1 "/usr/sbin/sshd" 3 "/usr/sbin/sshd" "… emits-invalidation
.ExecStartEx property a(sasasttttuii) 1 "/usr/sbin/sshd" 3 "/usr/sbin/sshd" "… emits-invalidation
.ExecStartPost property a(sasbttttuii) 0 emits-invalidation
.ExecStartPostEx property a(sasasttttuii) 0 emits-invalidation
.ExecStartPre property a(sasbttttuii) 1 "/usr/sbin/sshd" 2 "/usr/sbin/sshd" "… emits-invalidation
.ExecStartPreEx property a(sasasttttuii) 1 "/usr/sbin/sshd" 2 "/usr/sbin/sshd" "… emits-invalidation
.ExecStop property a(sasbttttuii) 0 emits-invalidation
.ExecStopEx property a(sasasttttuii) 0 emits-invalidation
.ExecStopPost property a(sasbttttuii) 0 emits-invalidation
.ExecStopPostEx property a(sasasttttuii) 0 emits-invalidation
.FileDescriptorStoreMax property u 0 const
.FinalKillSignal property i 9 const
.GID property u 4294967295 emits-change
.Group property s "" const
.GuessMainPID property b true const
.IOAccounting property b false -
.IODeviceLatencyTargetUSec property a(st) 0 -
.IODeviceWeight property a(st) 0 -
.IOReadBandwidthMax property a(st) 0 -
.IOReadBytes property t 18446744073709551615 -
.IOReadIOPSMax property a(st) 0 -
.IOReadOperations property t 18446744073709551615 -
.IOSchedulingClass property i 0 const
.IOSchedulingPriority property i 0 const
.IOWeight property t 18446744073709551615 -
.IOWriteBandwidthMax property a(st) 0 -
.IOWriteBytes property t 18446744073709551615 -
.IOWriteIOPSMax property a(st) 0 -
.IOWriteOperations property t 18446744073709551615 -
.IPAccounting property b false -
.IPAddressAllow property a(iayu) 0 -
.IPAddressDeny property a(iayu) 0 -
.IPEgressBytes property t 18446744073709551615 -
.IPEgressFilterPath property as 0 -
.IPEgressPackets property t 18446744073709551615 -
.IPIngressBytes property t 18446744073709551615 -
.IPIngressFilterPath property as 0 -
.IPIngressPackets property t 18446744073709551615 -
.IgnoreSIGPIPE property b true const
.InaccessiblePaths property as 0 const
...skipping...
.CollectMode property s "inactive" const
.ConditionResult property b true emits-change
.ConditionTimestamp property t 1597235861034899 emits-change
.ConditionTimestampMonotonic property t 5333881 emits-change
.Conditions property a(sbbsi) 1 "ConditionPathExists" false true "/et… emits-invalidation
.ConflictedBy property as 0 const
.Conflicts property as 1 "shutdown.target" const
.ConsistsOf property as 0 const
.DefaultDependencies property b true const
.Description property s "OpenBSD Secure Shell server" const
.Documentation property as 2 "man:sshd(8)" "man:sshd_config(5)" const
.DropInPaths property as 0 const
.FailureAction property s "none" const
.FailureActionExitStatus property i -1 const
.Following property s "" -
.FragmentPath property s "/lib/systemd/system/ssh.service" const
.FreezerState property s "running" emits-change
.Id property s "ssh.service" const
.IgnoreOnIsolate property b false const
.InactiveEnterTimestamp property t 0 emits-change
.InactiveEnterTimestampMonotonic property t 0 emits-change
.InactiveExitTimestamp property t 1597235861039525 emits-change
.InactiveExitTimestampMonotonic property t 5338505 emits-change
.InvocationID property ay 16 90 215 118 165 228 162 72 57 179 144… emits-change
.Job property (uo) 0 "/" emits-change
.JobRunningTimeoutUSec property t 18446744073709551615 const
.JobTimeoutAction property s "none" const
.JobTimeoutRebootArgument property s "" const
.JobTimeoutUSec property t 18446744073709551615 const
.JoinsNamespaceOf property as 0 const
.LoadError property (ss) "" "" const
.LoadState property s "loaded" const
.Names property as 2 "ssh.service" "sshd.service" const
.NeedDaemonReload property b false const
.OnFailure property as 0 const
.OnFailureJobMode property s "replace" const
.PartOf property as 0 const
.Perpetual property b false const
.PropagatesReloadTo property as 0 const
.RebootArgument property s "" const
.Refs property as 0 -
.RefuseManualStart property b false const
.RefuseManualStop property b false const
.ReloadPropagatedFrom property as 0 const
.RequiredBy property as 0 const
.Requires property as 3 "system.slice" "-.mount" "sysinit.tar… const
.RequiresMountsFor property as 1 "/run/sshd" const
.Requisite property as 0 const
.RequisiteOf property as 0 const
.SourcePath property s "" const
.StartLimitAction property s "none" const
.StartLimitBurst property u 5 const
.StartLimitIntervalUSec property t 10000000 const
.StateChangeTimestamp property t 1597235861208937 emits-change
.StateChangeTimestampMonotonic property t 5507917 emits-change
.StopWhenUnneeded property b false const
.SubState property s "running" emits-change
.SuccessAction property s "none" const
.SuccessActionExitStatus property i -1 const
.Transient property b false const
.TriggeredBy property as 0 const
.Triggers property as 0 const
.UnitFilePreset property s "enabled" -
.UnitFileState property s "enabled" -
.WantedBy property as 1 "multi-user.target" const
.Wants property as 0 const
Você pode ver por isso que a interface dbus é bastante poderosa.
Você pode perguntar: Por que esses aplicativos não se comunicam apenas por meio de soquetes ou arquivos?
DBus fornece uma interface comum. Você não precisa de lógica diferente para chamar métodos ou verificar propriedades com base no aplicativo com o qual está conversando. Você só precisa saber o nome do caminho.
Usei systemd
como exemplo porque é o que entendo melhor, mas existem muitos usos de dbus na maioria dos desktops. Tudo, desde autenticação até configurações de exibição, está disponível no dbus.
Responder2
Já existe uma ótima resposta detalhada do D-Bus por @Stewart, mas quero alterá-la com uma ideia de alto nível sobre o design do D-Bus.
A forma "tradicional" de comunicação entre processos (IPC) em sistemas UNIX e Linux usa soquetes diretamente, por exemplo, o processo A abre /var/run/a.socket
e o processo B lê/grava nele. Isso funciona muito bem para programas bem unidos que foram projetados para se comunicarem entre si.
No entanto, você pode querer ter comunicação entre os processos de dois programas onde o programa B nem existia quando o programa A foi escrito. O D-Bus tenta resolver esse problema fornecendo protocolos para comunicação e descoberta de serviços. Dessa forma, apenas a interface b precisava existir quando A foi escrita e o processo B implementa a interface b.
Você poderia, portanto, descrever o D-Bus como um "gerente" IPC.
Historicamente, as ferramentas de interface de linha de comando (CLI) geralmente também usam um gerenciador IPC, o shell, para se comunicar com programas arbitrários usando pipes. O problema com esta abordagem é que ela não fornece validação de dados, protocolos padronizados, etc. Portanto, só pode ser usada por usuários avançados. As ferramentas GUI em geral devem fazer isso "invisivelmente". No entanto, cada vez mais ferramentas CLI começam a usar o D-Bus, praticamente como uma alternativa ao sudo(1)
. Portanto, você pode executar, como um usuário sem privilégios, systemctl poweroff
e ele solicitará autenticação (isso pode ser comparado ao UAC no Windows). Dependendo do seu provedor de polkit, isso pode ser até mesmo um prompt da GUI. Pelo menos em teoria, esta abordagem é mais flexível e permite privilégios mais refinados e funciona sem binários setuid (como sudo
). Isso pode ser visto como um recurso de segurança.
Claro que, como abstração, introduz algum tipo de complexidade (pelo menos nas dependências dos programas). No entanto, quanto mais os programas fizerem uso (saudável) dele, menos oneroso será. Se você gosta do D-Bus e do desenvolvimento atual, não posso dizer. Mas os sistemas operacionais modernos tendem a fornecer muitos serviços cruciais fora do kernel (e agora movem o material histórico do kernel para fora novamente, no estilo microkernel) devido aos requisitos mais complexos da computação atual. Então, se você "apenas" quer um terminal "simples", tudo isso pode ser considerado "inchaço", mas a indústria exige isso por um bom motivo e cada vez mais desenvolvedores observam as vantagens de usar o D-Bus. É o substituto de hoje para o bom e velho pipe em seu shell (não a interface do sistema, na verdade o D-Bus faz uso, pipe()
etc.).
Responder3
No Unix tradicional, geralmente há pouca comunicação entre os programas em execução. Cada programa é executado em um espaço de endereço totalmente separado e interage apenas com o kernel. Esse modelo é simples e robusto, mas as permissões de acesso são geralmente muito grosseiras para ambientes de desktop, e a implementação de controle de acesso refinado é muito complexa em muitos casos.
Um exemplo onde o kernel refina o controle de acesso é o sistema de arquivos – programas sem privilégios podem enviar uma solicitação de gravação ao kernel, que é traduzida em uma solicitação de gravação enviada ao disco rígido sem violar a separação entre programas. Esta é uma camada bastante complexa e o controle ainda não é bom o suficiente para desktops modernos onde os usuários podem querer conectar um pendrive.
Para outras funções, como acesso à placa de som, por exemplo, o kernel implementa apenas um modelo de acesso simples: uma vez que um programa tenha acesso à placa de som, ele pode reproduzir e gravar som e manipular os controles do mixer, e não há mecanismo para revogar esse acesso, exceto encerrando o programa.
Em um ambiente de desktop, gostaríamos de um modelo mais refinado: o navegador deveria ser capaz de usar o microfone e a webcam somente depois de perguntar ao usuário, e quando um usuário efetua logout, qualquer programa em execução deve perder o acesso ao microfone, mas se o usuário quiser para executar um cálculo durante a noite, isso ainda deveria ser possível.
O sistema X window é um bom precedente para realizar o controle de acesso em um programa de usuário – a renderização para uma janela é feita enviando uma solicitação a outro programa que calcula o conteúdo final da tela que é exibida. Se a solicitação é traduzida em uma mudança visível no conteúdo da tela é decidido com base nas configurações atuais de controle de acesso: puxar uma janela para a frente dá acesso de gravação a uma área do espaço da tela para este programa, enviá-la para trás revoga esse acesso.
Os ambientes de desktop agora fornecem muitos desses programas mediadores, portanto, para cada função é necessário haver um protocolo de comunicação e um método para abrir um identificador para esse programa.
dbus fornece um protocolo genérico e um serviço de corretagem onde os programas podem solicitar conexão a um programa que fornece controle de acesso a funcionalidades específicas. Se o programa alvo já estiver em execução, o corretor apenas encaminhará as solicitações; se ainda não estiver em execução, o corretor iniciará o programa sob demanda, se souber como fazê-lo.
A funcionalidade equivalente no Windows é COM/DCOM em combinação com o registro.
Responder4
- eu habilitoocultoque deveria quebrar
dbus
. - eu tambémmudar o único
machine-id
quedbus
é gerado em cada inicialização viarc.local
(devuan também o gera em cada inicialização)
Tudo ainda parece funcionar no XFCE (alguns desktops, por exemplo, o gnome, podem sermais dependente dedbus
). Eu executo aplicativos atravésprisão de fogoportanto, perder quaisquer supostos benefícios de segurança dbus
não é realmente uma preocupação.
As seguintes distribuições Linux parecem funcionar bem sem dbus
& systemd
:
Haverá pequenos problemas, mas se você for razoavelmente competente, eles serão fáceis de resolver.