Назад | Перейти на главную страницу

Как настроить D-Bus и SSH X-Forwarding, чтобы SSH не зависал при выходе?

Я пытаюсь запускать различные приложения Gnome через X11 Forwarding и SSH. Некоторые приложения сначала запускают приложение dbus-launch. Проблема в том, что dbus-launch не закрывается при выходе из приложения X и, следовательно, должен быть уничтожен, прежде чем сеанс SSH может быть закрыт должным образом.

Я предполагаю, что проблема в том, что приложения X / Gnome не могут подключиться к главному демону шины сообщений и поэтому должны запускать свою собственную копию? Как я могу это исправить? Или что мне не хватает?

Вот пример. У меня включен X11 Forwarding, вроде все работает нормально.

[me@host ~]$ gnome-calculator &
[1] 4803

(здесь запускается программа gcalctool, которая отображается на моем удаленном X-сервере (Xming))

[me@host ~]$ ps
  PID TTY          TIME CMD
 4706 pts/0    00:00:00 bash
 4803 pts/0    00:00:00 gnome-calculator
 4807 pts/0    00:00:00 dbus-launch
 4870 pts/0    00:00:00 ps

(теперь, после закрытия приложения gcalctool в удаленном сеансе)

[me@host ~]$ ps
  PID TTY          TIME CMD
 4706 pts/0    00:00:00 bash
 4807 pts/0    00:00:00 dbus-launch
 4898 pts/0    00:00:00 ps

Обратите внимание, что dbus-launch все еще активен. И что хуже всего, это препятствует правильному закрытию SSH-соединения, пока оно не будет отключено.

Обратите внимание, что запущен общесистемный демон сообщений, как можно увидеть здесь:

[me@host ~]$ ps ax
 4696 ?     Ssl   0:00 dbus-daemon --system

Что мне здесь не хватает? Я никогда раньше не видел такого поведения. По-видимому, я когда-либо видел только приложения, которые могут беспрепятственно подключаться к демону шины сообщений? Я искал ответы в / etc / dbus-1, но не знаю, что искать.

Заранее спасибо за помощь.

[РЕДАКТИРОВАТЬ]

Хорошо, я понимаю, что у меня обычная проблема. Кажется, это довольно распространенное поведение, но без хорошего решения. Я испытываю зависание SSH, потому что dbus-launch все еще активен на tty. Но, похоже, нет хорошего способа заставить dbus-launch происходить незаметно.

Просмотр /etc/X11/xinit/xinitrc.d/00-start-message-bus.sh дает некоторое представление о том, что должно произойти с «нормальным» X-сеансом. Это, конечно, не работает при простом вызове X-приложения на удаленный X-сервер.

В качестве временного решения я добавил это в свой .bash_logout:

# ~/.bash_logout
pkill -u $USER -t `tty | cut -d '/' -f 3,4` dbus-launch

Это позволит завершить сеанс SSH, но это будет неудобно. Есть ли какие-нибудь лучшие решения? Как правильно запускать удаленные приложения X11, чтобы dbus не мешал?

На запуск dbus (1):

Если DBUS_SESSION_BUS_ADDRESS не установлен для процесса, который пытается использовать D-Bus, по умолчанию процесс будет пытаться вызвать dbus-launch с параметром --autolaunch, чтобы запустить новую шину сеанса или найти существующий адрес шины на дисплее X или в файле в ~ / .dbus / session-bus /

Каждый раз, когда происходит автозапуск, приложение, которое должно было запустить новую шину, оказывается в своем собственном маленьком мире; он может эффективно начать новый сеанс, если попытается использовать много шинных служб. Это может быть неоптимальным или даже полностью нарушенным, в зависимости от приложения и того, что оно пытается делать.

Есть две распространенные причины автозапуска. Один из них - ssh на удаленную машину.

Кажется, уловка состоит в том, чтобы заранее запустить dbus-daemon, чтобы программы могли его найти. Я использую:

[me@host ~]$ dbus-launch --exit-with-session gnome-terminal

который, помимо gnome-terminal, запускает dbus-daemon и устанавливает $ DBUS_SESSION_BUS_ADDRESS внутри gnome-terminal.

Любые X-программы, запускаемые из gnome-terminal, затем ведут себя нормально, а dbus-launch очищает себя после выхода из gnome-terminal.

У меня была такая же проблема при попытке запустить удаленную команду X и завершить сеанс после выхода из инструмента X.

Итак, я хотел бежать

ssh -X user@remotehost "firefox -no-remote"

Но пришлось использовать:

ssh -X user@remotehost 'export \`dbus-launch\`; dbus-launch firefox -no-remote; kill -TERM $DBUS_SESSION_BUS_PID'

После закрытия firefox это также закроет сеанс ssh.

Обновить:

Кажется, что на сервере остается нагрузка процессов dbus-daemon, поэтому это не оптимально, добавление --exit-with-session для обеих учетных записей не помогает, потому что это возвращает исходное поведение

обновление 2: это работает, когда я использую одинарные кавычки (как предлагает @lobo) и добавляю kill -TERM $DBUS_SESSION_BUS_PID чтобы убить оставшиеся процессы dbus-daemon, как предлагает Holgr Joukl из https://blog.dhampir.no/content/how-to-prevent-ssh-x-from-hanging-on-exit-when-dbus-is-used)

Интересно, не возникает ли проблема из-за неизвестного или не завершающегося сеанса dbus.

Действительно, когда сеанс SSH открыт, он не запускает сеанс dbus. Некоторые программы могут запускать его, но тогда сеанс не знает об этом (следовательно, не может его закрыть).

Незнание о сеансе dbus также означает, что программы, использующие dbus, но не запускающие его сами, будут иметь проблемы.

Разделы dbus предназначены для каждой машины и для каждого дисплея X11. Их информация хранится в $ HOME / .dbus / session-bus / - однако упомянутый там процесс может быть закрыт, поэтому необходима дополнительная проверка, чтобы определить, нужен ли запуск dbus или нет. Затем переменные должны быть экспортированы в сеанс.

Тогда работает как шарм :)

Я поместил в свой файл .bash_profile следующее:

# set dbus for remote SSH connections
if [ -n "$SSH_CLIENT" -a -n "$DISPLAY" ]; then
    machine_id=$(LANGUAGE=C hostnamectl|grep 'Machine ID:'| sed 's/^.*: //')
    x_display=$(echo $DISPLAY|sed 's/^.*:\([0-9]\+\)\(\.[0-9]\+\)*$/\1/')
    dbus_session_file="$HOME/.dbus/session-bus/${machine_id}-${x_display}"
    if [ -r "$dbus_session_file" ]; then
            export $(grep '^DBUS.*=' "$dbus_session_file")
            # check if PID still running, if not launch dbus
            ps $DBUS_SESSION_BUS_PID | tail -1 | grep dbus-daemon >& /dev/null
            [ "$?" != "0" ] && export $(dbus-launch) >& /dev/null
    else
            export $(dbus-launch) >& /dev/null
    fi
fi

примечания: hostnamectl является частью systemd и позволяет получить идентификатор машины, dbus-launch отображает нужные нам переменные; используя export $(dbus-launch) мы получаем вывод dbus-launch и экспортируем переменные

если вы хотите, чтобы это выполнялось на неинтерактивном сеансе (например, при запуске команды из ssh), попробуйте вместо этого поместить его в .bashrc (но помните, что bashrc выполняется в КАЖДОЙ открытой оболочке)