
dbus
Предполагается, что он предоставит «простой способ взаимодействия приложений друг с другом».
Но я все еще не уверен, для чего это полезно на практике. Я никогда не видел ситуации, когда это dbus
было бы полезно, я вижу только предупреждения о том, что какой-то dbus
компонент столкнулся с ошибками, например, когда я запускаю terminator из командной строки (чтобы я мог видеть ошибки):
Error retrieving accessibility bus address: org.freedesktop.DBus.Error.ServiceUnknown: The name org.a11y.Bus was not provided by any .service files
Я избавился от вышеуказанной ошибки, добавив NO_AT_BRIDGE=1
в /etc/environment
. Понятия не имею, что это делает.
Почти все приложения gui, похоже, связаны с dbus
. Некоторые из них можно запускать без dbus
, например:
terminator --no-dbus
Я не вижу никакой разницы в поведении. Что должно перестать работать, если terminator
запустить без dbus
?
Кроме того, я попробовал отключить различные компоненты dbus, чтобы посмотреть, что перестает работать:
Я удалил, /etc/X11/Xsession.d/95dbus_update-activation-env
просто чтобы посмотреть, что будет. Там был следующий код:
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
Насколько я могу судить, все работает одинаково. Какова была цель приведенного выше скрипта?
В какой ситуации моим приложениям будет полезно общаться друг с другом через dbus
?
Есть ли приложения, которые не работают без dbus
?
Моя система — Debian Buster, и я использую простую среду Openbox (без какой-либо среды рабочего стола, такой как Gnome или KDE)
решение1
dbus
делает именно то, что вы сказали: обеспечивает двустороннюю связь между приложениями.
Для вашего конкретного примера, который вы упомянули terminator
. Отman-страница терминатора, мы видим:
--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.
Итак, если вы сделаете это из другого терминала (konsole, xterm, gnome-terminal):
$ terminator &
$ terminator --new-tab &
Вы увидите, что первая команда открывает новое окно. Вторая команда открывает новую вкладку в первом окне. Это делается вторым процессом, который использует dbus для поиска первого процесса, запрашивает у него открытие новой вкладки и затем завершается.
Если вы делаете это с другого терминала:
$ terminator --no-dbus &
$ terminator --new-tab &
Вы увидите, что первая команда открывает новое окно. Вторая команда не может найти dbus первого окна, поэтому она запускает новое окно. Я установил terminator, чтобы проверить это, и это правда.
Кроме того, я подозреваю, что это затронет polkit. Polkit использует dbus для повышения привилегий для приложений с графическим интерфейсом. Это похоже sudo
на мир графического интерфейса. Если вы находитесь в gnome и видите, что весь экран перекрывается, пока вас просят ввести пароль администратора, это polkit в действии. Я подозреваю, что вы не получите этого приглашения ни в одном приложении с графическим интерфейсом, из которого вы запустите, terminator
если у вас есть --no-dbus
. Он либо не сможет пройти аутентификацию, либо вернется к какой-либо терминальной аутентификации. Из terminator
try pkexec ls
. Это будет работать ls
с повышенными привилегиями. Посмотрите, отличается ли это с --no-dbus
опцией и без нее. У меня нет агента polkit в моем оконном менеджере (i3), поэтому я не могу это проверить.
Я в основном знаком с dbus в контексте systemd, поэтому остальная часть моего ответа будет взята оттуда.
Есть ли приложения, которые не работают без
dbus
?
Да. Возьмите systemctl
. systemctl status
выполнит запрос к "org.freedesktop.systemd1"
и предоставит его вам. systemctl start
вызовет метод dbus и передаст единицу в качестве аргумента этому методу. systemd
получит вызов и выполнит действие.
Если вы хотите предпринять действие в ответ на изменение состояний единицы systemd (например, foo.service), вы можете получить файловый дескриптор для интерфейса org.freedesktop.DBus.Properties
с путем /org/freedesktop/systemd1/unit/foo_2eservice
и членом PropertiesChanged
. Настройте inotify
на этом FD, и у вас внезапно появится способ реагировать на запуск, остановку, сбой службы и т. д.
Если вы хотите посмотреть, что доступно на системной шине данных для определенного устройства (например, ssh.service
), попробуйте выполнить следующую команду:
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
Из этого видно, что интерфейс dbus довольно мощный.
Вы можете спросить: почему эти приложения просто не взаимодействуют через сокеты или файлы?
DBus предоставляет общий интерфейс. Вам не нужна другая логика для вызова методов или проверки свойств в зависимости от приложения, с которым вы общаетесь. Вам просто нужно знать имя пути.
Я использовал systemd
в качестве примера, потому что это то, что я лучше всего понимаю, но есть куча применений dbus на большинстве настольных компьютеров. Все, от аутентификации до настроек отображения, доступно на dbus.
решение2
@Stewart уже дал отличный подробный ответ о D-Bus, но я хочу дополнить его общей идеей о дизайне D-Bus.
«Традиционный» способ межпроцессного взаимодействия (IPC) в системах UNIX и Linux напрямую использует сокеты, например, процесс A открывает, /var/run/a.socket
а процесс B читает/записывает в него. Это работает довольно хорошо для тесно связанных программ, которые были разработаны для взаимодействия друг с другом.
Однако вам может понадобиться связь между процессами двух программ, где программа B даже не существовала, когда была написана программа A. D-Bus пытается решить эту проблему, предоставляя протоколы для связи и обнаружения служб. Таким образом, только интерфейс b должен был существовать, когда была написана программа A, а процесс B реализует интерфейс b.
Таким образом, D-Bus можно охарактеризовать как «менеджер» IPC.
Исторически инструменты интерфейса командной строки (CLI) обычно также используют менеджер IPC, оболочку, для связи с произвольными программами с помощью каналов. Проблема с этим подходом в том, что он не обеспечивает проверку данных, стандартизированные протоколы и т. д. Таким образом, он может использоваться только опытными пользователями. Инструменты GUI в целом должны делать это «невидимо». Однако все больше и больше инструментов CLI начинают использовать D-Bus, в значительной степени как альтернативу sudo(1)
. Так что вы можете, как непривилегированный пользователь, выполнить systemctl poweroff
, и он запросит у вас аутентификацию (это можно сравнить с UAC в Windows). В зависимости от вашего поставщика polkit это может быть даже запрос GUI. По крайней мере, в теории, этот подход более гибкий и допускает более тонкие привилегии и работает без двоичных файлов setuid (например sudo
). Это можно рассматривать как функцию безопасности.
Конечно, как абстракция, это вносит некоторую сложность (по крайней мере, в зависимости программ). Однако, чем больше программ (разумно) используют его, тем меньше это бремени. Нравится ли вам D-Bus и текущая разработка, я не могу вам сказать. Но современные операционные системы, как правило, предоставляют множество важных служб за пределами ядра (и теперь снова выносят исторические вещи ядра, микроядерные) из-за более сложных требований современных вычислений. Так что, если вам «просто» нужен «простой» терминал, все это может считаться «раздутым», но индустрия требует этого по веской причине, и все больше разработчиков отмечают преимущества использования D-Bus. Это сегодняшняя замена для старого доброго конвейера в вашей оболочке (не системный интерфейс, на самом деле D-Bus использует pipe()
и т. д.).
решение3
В традиционном Unix обычно мало общения между запущенными программами. Каждая программа работает в полностью отдельном адресном пространстве и взаимодействует только с ядром. Эта модель проста и надежна, но права доступа в основном слишком грубы для сред рабочего стола, а реализация мелкозернистого контроля доступа во многих случаях слишком сложна.
Одним из примеров, где ядро улучшает контроль доступа, является файловая система — непривилегированные программы могут отправлять запрос на запись ядру, который преобразуется в запрос на запись, отправляемый на жесткий диск, не нарушая разделения между программами. Однако это довольно сложный уровень, и контроль все еще недостаточно хорош для современных настольных компьютеров, где пользователи могут захотеть подключить USB-накопитель.
Для других функций, например, доступа к звуковой карте, ядро реализует только простую модель доступа: как только программа получает доступ к звуковой карте, она может воспроизводить и записывать звук, а также управлять элементами управления микшером, и не существует механизма для отзыва этого доступа, кроме завершения программы.
В среде настольного компьютера нам нужна более совершенная модель: браузер должен иметь возможность использовать микрофон и веб-камеру только после запроса пользователя, а когда пользователь выходит из системы, любая запущенная программа должна потерять доступ к микрофону, но если пользователь захочет запустить вычисление ночью, это все равно должно быть возможно.
Система X Window является хорошим прецедентом для осуществления контроля доступа в пользовательской программе — рендеринг в окно выполняется путем отправки запроса в другую программу, которая вычисляет конечное содержимое экрана, которое отображается. Будет ли запрос преобразован в видимое изменение содержимого экрана, решается на основе текущих настроек контроля доступа: перемещение окна на передний план дает этой программе доступ на запись в область экранного пространства, отправка его на задний план отменяет этот доступ.
В настоящее время среды рабочего стола предоставляют множество таких программ-посредников, поэтому для каждой функции должен быть протокол связи и метод открытия дескриптора этой программы.
dbus предоставляет общий протокол и брокерскую службу, где программы могут запрашивать подключение к программе, предоставляющей контроль доступа к определенным функциям. Если целевая программа уже запущена, брокер просто пересылает запросы, если она еще не запущена, брокер запускает программу по требованию, если знает, как это сделать.
Эквивалентная функциональность в Windows — это COM/DCOM в сочетании с реестром.
решение4
- Я включаюхидепидкоторый должен сломаться
dbus
. - Я такжеизменить уникальный
machine-id
которыйdbus
генерируется при каждой загрузке черезrc.local
(devuan также генерирует его при каждой загрузке)
Кажется, все по-прежнему работает под XFCE (некоторые рабочие столы, например, gnome, могут работать)больше зависит отdbus
). Я запускаю приложения черезпожарная тюрьмапоэтому потеря каких-либо предполагаемых преимуществ безопасности dbus
на самом деле не является поводом для беспокойства.
Следующие дистрибутивы Linux, похоже, прекрасно работают без dbus
& systemd
:
- девуанский(на базе Debian)
- артикс(На базе Arch Linux)
- антикс(на базе Debian)
Могут возникнуть незначительные проблемы, но если вы достаточно компетентны, их легко устранить.