Para que o D-Bus é praticamente útil?

Para que o D-Bus é praticamente útil?

dbussupostamente 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 dbusfosse útil, só vejo avisos de que algum dbuscomponente 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=1ao /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-envsó 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

dbusfaz 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 sudomundo 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, terminatorse tiver o --no-dbus. Ele falhará na autenticação ou recorrerá a alguma autenticação de terminal. De terminatortentar pkexec ls. Isso será executado lscom privilégios elevados. Veja se é diferente com e sem a --no-dbusopçã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 statusemitirá uma consulta para "org.freedesktop.systemd1"e apresentará isso a você. systemctl startchamará um método dbus e passará a unidade como argumento para esse método. systemdrecebe 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.Propertiescom path /org/freedesktop/systemd1/unit/foo_2eservicee member PropertiesChanged. Configure um inotifynesse 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 systemdcomo 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.sockete 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 poweroffe 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

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 dbusnão é realmente uma preocupação.

As seguintes distribuições Linux parecem funcionar bem sem dbus& systemd:

  • devuan(baseado em Debian)
  • artix(baseado em Arch Linux)
  • antix(baseado em Debian)

Haverá pequenos problemas, mas se você for razoavelmente competente, eles serão fáceis de resolver.

informação relacionada