dbus и KDE · 6 min read · Jan 03, 2026
Интеграция dbus и KDE: запуск и остановка сессионной части dbus с KDM.
Интеграция dbus и KDE: запуск и остановка сессионной части dbus с KDM.
Содержание
- Введение
- Настройка конфигурации KDM
- Запуск демона сессии dbus и доступ к переменным окружения.
2.1 О файлах запуска Bash.
2.2 Запуск сессионной части dbus
2.3 Остановка сессионной части dbus
2.4 Один пользователь вошел более одного раза
0. Введение
С некоторых пор многие приложения используют D-BUS. Это касается KDE 3.5, текущей стабильной версии KDE. С предстоящим KDE 4 D-BUS становится все более важным, заменяя DCOP.
В этом руководстве я хочу описать способ запуска и остановки части dbus, зависящей от пользователя и сессии. Основные цели, которые я преследую с этим подходом, следующие:
- сделать доступными переменные окружения, важные для приложений, работающих с d-bus;
- убедиться, что сессионная часть dbus не запускается более одного раза для одного пользователя;
- убедиться, что сессионная часть dbus останавливается, когда сессия пользователя заканчивается;
Я предполагаю, что пользователь входит в систему с KDM, менеджером входа для KDE 3.5. Эта конструкция также может быть использована с другими менеджерами входа (XDM, GDM).
KDM имеет возможность запускать скрипты в начале сессии (при запуске) и в конце (сброс). Один из них может запускать (и останавливать) сессионную часть dbus.
1. KDM: файлы
KDM использует несколько файлов для запуска и остановки:
. Xstartup
запускается от имени root после успешного входа пользователя.
. Xsession
работает с правами авторизованного пользователя, чтобы запустить желаемую сессию (KDE).
. Xreset
запускается от имени root после завершения сессии пользователя.
Где Xstartup — это место для запуска процессов, Xreset — это место для отмены этих команд.
Для получения дополнительной информации об этих файлах смотрите справочник KDM.
Добавив следующий код в файл Xstartup:
-- snip --
for script in /etc/session.d/kdm/startup/*.sh; do
if [ -x $script ]; then
eval $script $USER kdm
fi;
done;и код в файл Xreset:
-- snip --
for script in /etc/session.d/kdm/reset/*.sh; do
if [ -x $script ]; then
eval $script $USER kdm
fi;
done;Создайте директории, куда будут помещены скрипты:
install -m755 -d /etc/session.d/kdm/startup
install -m755 -d /etc/session.d/kdm/reset
install -m755 -d /etc/session.d/scripts/start
install -m755 -d /etc/session.d/scripts/stopФайлы в этих директориях должны быть доступны для каждого обычного пользователя: поэтому права доступа составляют 755.
Все скрипты в этих директориях должны иметь одинаковые права: 755.
Каждый пользователь должен иметь возможность выполнять скрипт, но только root может их изменять.
1. Запуск демона сессии dbus и доступ к переменным окружения
Пакет dbus разделен на две части: одна системная часть и одна для (каждой) сессии/пользователя. Системная часть (демон) запускается при загрузке с особыми привилегиями выделенного пользователя. Сессионная часть (также демон) должна быть запущена, когда начинается сессия для пользователя, и остановлена, когда сессия заканчивается.
Конструкция с kdm, которую я использую здесь, идеальна для этого. Один скрипт в каталоге startup для запуска демона сессии для пользователя, работающий с привилегиями этого пользователя, и один в каталоге reset, другой скрипт должен остановить этот демон.
Но это не так просто. Некоторые переменные (DBUS_SESSION_BUS_ADDRESS и DBUS_SESSION_BUS_PID) должны быть доступны в окружении для каждого приложения, которое работает с dbus. На мой взгляд, установка этих переменных должна происходить в скриптах запуска bash. Тогда, какой бы скрипт или приложение вы ни запускали, эти переменные будут установлены на правильное значение.
1.1 О файлах запуска Bash
Демон сессии dbus создает файл, который содержит переменные окружения. Как уже упоминалось, этот файл должен быть прочитан (подключен) bash, когда он запускается для этого пользователя.
Когда bash запускается через “login” как интерактивная оболочка входа, он читает /etc/profile и ~/.bash_profile. Bash также запускается через “kdm”, и файлы /etc/profile и ~/.bash_profile подключаются.
Моя идея заключается в том, чтобы сохранить вывод команды
dbus-launch --auto-syntaxв файл
$HOME/.dbus-session
Этот файл “подключается”, когда bash запускается. Это не происходит автоматически, но вам нужно добавить следующий скрипт в /etc/profile.d :
cat >> /etc/profile.d/dbus-session.sh << "EOF"
if [ -f $HOME/.dbus-session ]; then
. $HOME/.dbus-session
fi;
EOFТаким образом, переменные окружения становятся доступными, когда Bash запускается.
1.2 Запуск сессионной части dbus
Я предполагаю, что dbus установлен и запускается при загрузке.
Создайте скрипт в каталоге /etc/session.d/scripts/start dbus-session-start.sh:
cd /etc/session.d/scripts/start
cat >> dbus-session-start.sh << "EOF"
#!/bin/bash
retcode=0;
userid=$1
userproperties=$(getent passwd | grep -m 1 -E "^$userid")
homedir=$(echo $userproperties | cut -d ":" -f 6);
gidnr=$(echo $userproperties | cut -d ":" -f 4);
uidnr=$(echo $userproperties | cut -d ":" -f 3);
if [ -d $homedir ]; then
#
# проверьте, запущен ли уже dbus-daemon
# dbus-daemon должен быть запущен пользователем (uidnr), который входит в систему
#
if [ -f $homedir/.dbus-session ]; then
# проверьте, что dbus-daemon для этого пользователя запущен с pid
# в файле .dbus-session
# pid согласно команде ps
ps_dbus_session_pid=$(ps aux | grep -m 1 -E "^$userid.*dbus-daemon.*session.*"
| grep -v "grep" | sed 's@[[:space:]][[:space:]]*@ @g' | cut -d " " -f 2)
# прочитайте pid из файла .dbus-session
. $homedir/.dbus-session
# проверьте, совпадают ли они
if [ -z "$ps_dbus_session_pid" ]; then
# dbus для этого пользователя не запущен
rm $homedir/.dbus-session
elif [ $DBUS_SESSION_BUS_PID -ne $ps_dbus_session_pid ]; then
# что-то не так: остановите dbus-daemon для этого пользователя
# и удалите файл .dbus-session
if [ $(id -u) -eq 0 ]; then
sudo -H -u $userid sh -c "kill $ps_dbus_session_pid"
elif [ $(id -u) -eq $uidnr ]; then
kill -SIGTERM $ps_dbus_session_pid;
fi
rm $homedir/.dbus-session
fi
fi
if [ ! -f $homedir/.dbus-session ]; then
# запускайте сессию dbus только если файл .dbus-session не найден
# в домашнем каталоге пользователя
if [ $(id -u) -eq 0 ]; then
sudo -u $userid -H /bin/sh -c "dbus-launch --auto-syntax > $homedir/.dbus-session"
retcode=$?
chown $uidnr:$gidnr $homedir/.dbus-session
elif [ $(id -u) -eq $uidnr ]; then
dbus-launch --auto-syntax > $homedir/.dbus-session
retcode=$?
fi
fi
fi;
if [ $retcode -ne 0 ]; then
echo "Ошибка с dbus ($retcode)."
fi;
exit $retcode
EOFchmod --verbose --mode 755 /etc/session.d/scripts/start/dbus-session-start.sh
ln -v -sf ../../scripts/start/dbus-session-start.sh /etc/session.d/kdm/startup/10dbus.shЭтот скрипт, выполняемый KDM при запуске, запустит демон сессии dbus для этого пользователя и создаст файл .dbus-session в домашнем каталоге этого пользователя, содержащий все переменные dbus.
Он сделает это только в том случае, если dbus уже не запущен для этого пользователя.
Теперь, когда bash запускается при входе, он читает (подключает) этот файл.
Как вы видите, я разделил запуск dbus на две части:
- dbus-session-start.sh, выполняется, когда начинается (kdm) сессия
- .dbus-session, подключается, когда начинается (bash) сессия, может подключаться несколько раз
Кроме того, я использую параметр –auto-syntax, где предполагаю, что используется Bash. Так что я мог бы использовать здесь –sh-syntax, но это работает.
И Sudo необходим для запуска dbus-launcher от имени пользователя, который входит в систему, потому что KDM запускает этот скрипт от имени root. (на самом деле скрипт проверяет идентификатор учетной записи, выполняющей этот скрипт. Если это root (id = 0), то используется sudo для переключения на пользователя, начинающего сессию. Когда идентификатор и идентификатор пользователя, входящего в систему, совпадают, ничего делать не нужно.
2.3 Остановка сессионной части dbus
Создание скрипта dbus-session-stop.sh в каталоге сброса:
cd /etc/session.d/scripts/stop
cat >> dbus-session-stop.sh << "EOF"
#!/bin/bash
retcode=0;
userid=$1
userproperties=$(getent passwd | grep -m 1 -E "^$userid")
homedir=$(echo $userproperties | cut -d ":" -f 6);
gidnr=$(echo $userproperties | cut -d ":" -f 4);
uidnr=$(echo $userproperties | cut -d ":" -f 3);
if [ -f $homedir/.dbus-session ]; then
. $homedir/.dbus-session
if [ -n "$DBUS_SESSION_BUS_PID" ]; then
if [ $(id -u) -eq 0 ]; then
sudo -u $userid -H /bin/sh -c "kill $DBUS_SESSION_BUS_PID"
retcode=$?
rm $homedir/.dbus-session
elif [ $(id -u) -eq $uidnr ]; then
kill $DBUS_SESSION_BUS_PID
retcode=$?
rm $homedir/.dbus-session
fi
fi
fi;
if [ $retcode -ne 0 ]; then
echo "Ошибка с dbus ($retcode)."
fi;
exit $retcode
EOFchmod --verbose --mode 755 dbus-session-stop.sh
ln -v -sf ../../scripts/stop/dbus-session-stop.sh /etc/session.d/kdm/reset/90dbus.shЭтот скрипт останавливает сессионную часть dbus-daemon.
2.4 Один пользователь вошел более одного раза
Для большинства ситуаций эта конструкция достаточно хороша. Большинство пользователей имеют одну сессию одновременно. Теперь что происходит, когда пользователь имеет более одной сессии одновременно? Необходимо ли запускать сессионную часть dbus для каждой сессии или одного экземпляра достаточно?
Эта конструкция не позволяет иметь более одного dbus-daemon на пользователя. Я думаю, что этого должно быть достаточно.
CHANGELOG:
[2006-01-18]
- Первоначальное руководство
[2006-07-18] - Изменены скрипты bash
[2006-09-09] - добавлена проверка, чтобы увидеть, запущен ли dbus-daemon для этого пользователя и правильна ли информация, найденная в .dbus-session
Get new posts in your inbox
No spam. Unsubscribe anytime.