
dbus
se supone que proporciona "una forma sencilla para que las aplicaciones se comuniquen entre sí".
Pero todavía no estoy seguro de para qué sirve en la práctica. Nunca he visto una situación en la que dbus
sea útil, solo veo advertencias de que algún dbus
componente ha experimentado errores, como cuando inicio Terminator desde la línea de comandos (para poder ver los errores):
Error retrieving accessibility bus address: org.freedesktop.DBus.Error.ServiceUnknown: The name org.a11y.Bus was not provided by any .service files
Me deshice del error anterior agregando NO_AT_BRIDGE=1
a /etc/environment
. No tengo idea de lo que eso hace.
Casi todas las aplicaciones gui parecen estar vinculadas con dbus
. Algunos permiten iniciar sin dbus
, es decir:
terminator --no-dbus
No veo ninguna diferencia en el comportamiento. ¿Qué se supone que deja de funcionar cuando terminator
se empieza sin dbus
?
Además, intenté deshabilitar varios componentes de dbus para ver qué deja de funcionar:
Lo he borrado /etc/X11/Xsession.d/95dbus_update-activation-env
sólo para ver qué pasa. Contenía el siguiente 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
Todo funciona igual, hasta donde yo sé. ¿Cuál fue el propósito del guión anterior?
¿En qué situación sería útil que mis aplicaciones se comunicaran entre sí a través de dbus
?
¿Hay aplicaciones que no funcionan sin ellas dbus
?
Mi sistema es Debian Buster y estoy usando un entorno openbox simple (sin ningún entorno de escritorio como Gnome o KDE)
Respuesta1
dbus
Hace exactamente lo que dijiste: permite la comunicación bidireccional entre aplicaciones.
Para su ejemplo específico que mencionó terminator
. Depágina de manual de terminador, 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.
Entonces, si haces esto desde otra terminal (konsole, xterm, gnome-terminal):
$ terminator &
$ terminator --new-tab &
Verás que el primer comando abre una nueva ventana. El segundo comando abre una nueva pestaña en la primera ventana. Esto lo hace el segundo proceso usando dbus para encontrar el primer proceso, pidiéndole que abra una nueva pestaña y luego saliendo.
Si haces esto desde otra terminal:
$ terminator --no-dbus &
$ terminator --new-tab &
Verás que el primer comando abre una nueva ventana. El segundo comando no encuentra el dbus de la primera ventana, por lo que abre una nueva ventana. Instalé Terminator para probar esto y es cierto.
Además, sospecho que polkit se vería afectado. Polkit usa dbus para elevar los privilegios de las aplicaciones GUI. Es como el sudo
mundo GUI. Si está en gnome y ve que se cubre toda la pantalla mientras se le solicita la contraseña del administrador, eso es polkit en acción. Sospecho que no recibirá ese mensaje en ninguna aplicación GUI desde la que inicie terminator
si tiene --no-dbus
. No podrá autenticarse o recurrirá a alguna autenticación de terminal. De terminator
intentarlo pkexec ls
. Eso se ejecutará ls
con privilegios elevados. Vea si es diferente con y sin la --no-dbus
opción. No tengo un agente polkit en mi administrador de ventanas (i3), así que no puedo probarlo.
Conozco principalmente dbus en términos de systemd, así que de ahí vendrá el resto de mi respuesta.
¿Hay aplicaciones que no funcionan sin ellas
dbus
?
Sí. Llevar systemctl
. systemctl status
emitirá una consulta a "org.freedesktop.systemd1"
y se la presentará. systemctl start
llamará a un método dbus y pasará la unidad como argumento a ese método. systemd
recibe la llamada y realiza la acción.
Si desea tomar medidas en respuesta a un cambio de estado de una unidad systemd (es decir, foo.service), puede obtener un descriptor de archivo para la interfaz org.freedesktop.DBus.Properties
con ruta /org/freedesktop/systemd1/unit/foo_2eservice
y miembro PropertiesChanged
. Configure un inotify
FD y de repente tendrá una manera de reaccionar ante el inicio, la detención, la falla de un servicio, etc.
Si desea ver lo que está disponible en systemd dbus para una unidad específica (es decir ssh.service
), pruebe 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
Puedes ver en esto que la interfaz dbus es bastante poderosa.
Quizás se pregunte: ¿Por qué estas aplicaciones no se comunican simplemente a través de sockets o archivos?
DBus proporciona una interfaz común. No necesita una lógica diferente para llamar a métodos o verificar propiedades según la aplicación con la que está hablando. Sólo necesitas saber el nombre del camino.
Lo he usado systemd
como ejemplo porque es lo que mejor entiendo, pero hay muchísimos usos de dbus en la mayoría de los escritorios. Todo, desde la autenticación hasta la configuración de visualización, está disponible en dbus.
Respuesta2
Ya existe una excelente respuesta detallada de D-Bus por parte de @Stewart, pero quiero modificarla con una idea de alto nivel sobre el diseño de D-Bus.
La forma "tradicional" de comunicación entre procesos (IPC) en sistemas UNIX y Linux utiliza sockets directamente, por ejemplo, el proceso A abre /var/run/a.socket
y el proceso B lee/escribe. Esto funciona bastante bien para programas muy unidos que fueron diseñados para comunicarse entre sí.
Sin embargo, es posible que desee tener comunicación entre los procesos de dos programas donde el programa B ni siquiera existía cuando se escribió el programa A. D-Bus intenta resolver este problema proporcionando protocolos de comunicación y descubrimiento de servicios. De esa manera, solo era necesario que existiera la interfaz b cuando se escribió A y el proceso B implementa la interfaz b.
Por tanto, se podría describir a D-Bus como un "administrador" de IPC.
Históricamente, las herramientas de interfaz de línea de comandos (CLI) suelen utilizar también un administrador de IPC, el shell, para comunicarse con programas arbitrarios mediante canalizaciones. El problema con este enfoque es que no proporciona validación de datos, protocolos estandarizados, etc. Por lo tanto, sólo lo pueden utilizar usuarios avanzados. Las herramientas GUI en general deberían hacer esto de forma "invisible". Sin embargo, cada vez más herramientas CLI comienzan a utilizar D-Bus, prácticamente como una alternativa a sudo(1)
. Entonces, como usuario sin privilegios, puede ejecutar systemctl poweroff
y se le solicitará autenticación (esto se puede comparar con el UAC en Windows). Dependiendo de su proveedor de polkit, esto puede ser incluso un mensaje de GUI. Al menos en teoría, este enfoque es más flexible y permite privilegios más detallados y funciona sin binarios setuid (como sudo
). Esto puede verse como una característica de seguridad.
Por supuesto, como abstracción, introduce algún tipo de complejidad (al menos en las dependencias de los programas). Sin embargo, cuanto más programas lo utilicen (sanamente), menor será la carga. Si te gusta D-Bus y el desarrollo actual no te lo puedo decir. Pero los sistemas operativos modernos tienden a proporcionar muchos servicios cruciales fuera del núcleo (y ahora sacan de nuevo el material histórico del núcleo, al estilo microkernel) debido a los requisitos más complejos de la informática actual. Por lo tanto, si "sólo" quieres un terminal "simple", todo esto podría considerarse "inflado", pero la industria lo exige por una buena razón y cada vez más desarrolladores notan las ventajas de usar D-Bus. Es el reemplazo actual de la vieja tubería en su shell (no la interfaz del sistema, en realidad D-Bus la utiliza, pipe()
etc.).
Respuesta3
En Unix tradicional, suele haber poca comunicación entre los programas en ejecución. Cada programa se ejecuta en un espacio de direcciones completamente separado y solo interactúa con el kernel. Este modelo es simple y robusto, pero los permisos de acceso son en su mayoría demasiado generales para entornos de escritorio, y la implementación de un control de acceso detallado es demasiado compleja en muchos casos.
Un ejemplo en el que el kernel refina el control de acceso es el sistema de archivos: los programas sin privilegios pueden enviar una solicitud de escritura al kernel, que se traduce en una solicitud de escritura enviada al disco duro sin violar la separación entre programas. Sin embargo, esta es una capa bastante compleja y el control aún no es lo suficientemente fino para las computadoras de escritorio modernas donde los usuarios pueden querer conectar una memoria USB.
Para otras funciones, como por ejemplo el acceso a la tarjeta de sonido, el núcleo sólo implementa un modelo de acceso simple: una vez que un programa tiene acceso a la tarjeta de sonido, puede reproducir y grabar sonido y manipular los controles del mezclador, y no existe ningún mecanismo para revocar ese acceso excepto terminando el programa.
En un entorno de escritorio, querríamos un modelo más fino: el navegador debería poder usar el micrófono y la cámara web solo después de preguntarle al usuario, y cuando un usuario cierra sesión, cualquier programa en ejecución debería perder el acceso al micrófono, pero si el usuario quiere ejecutar un cálculo durante la noche, eso aún debería ser posible.
El sistema X window es un buen precedente para realizar control de acceso en un programa de usuario: la representación en una ventana se realiza enviando una solicitud a otro programa que calcula el contenido final de la pantalla que se muestra. Si la solicitud se traduce en un cambio visible en el contenido de la pantalla se decide en función de la configuración de control de acceso actual: arrastrar una ventana hacia el frente otorga acceso de escritura a un área del espacio de la pantalla para este programa, enviarla hacia atrás revoca ese acceso.
Los entornos de escritorio ahora proporcionan muchos de estos programas mediadores, por lo que para cada función debe haber un protocolo de comunicaciones y un método para abrir un identificador para ese programa.
dbus proporciona un protocolo genérico y un servicio de intermediario donde los programas pueden solicitar conectarse a un programa que proporciona control de acceso a una funcionalidad específica. Si el programa de destino ya se está ejecutando, el corredor simplemente reenviará las solicitudes; si aún no se está ejecutando, el corredor iniciará el programa a pedido si sabe cómo hacerlo.
La funcionalidad equivalente en Windows es COM/DCOM en combinación con el registro.
Respuesta4
- yo habilitoescondidaque se supone que debe romperse
dbus
. - Yo tambiéncambiar lo único
machine-id
quedbus
genera en cada arranque a través derc.local
(devuan también lo genera en cada arranque)
Todo parece funcionar todavía bajo XFCE (algunos escritorios, por ejemplo, gnome, pueden sermás dependiente dedbus
). Ejecuto aplicaciones a travéscárcel de bomberospor lo que perder cualquier supuesto beneficio de seguridad dbus
no es realmente una preocupación.
Las siguientes distribuciones de Linux parecen funcionar bien sin dbus
& systemd
:
Habrá problemas menores, pero si eres razonablemente competente, son fáciles de solucionar.