Вопрос или проблема
Может ли один пользователь, или, возможно, root, управлять пользовательскими уровнями systemd услуг другого пользователя?
Я попробовал sudo -u <какой-то пользователь> systemctl --user restart <какая-то услуга>
, но он жалуется на dbus: Failed to get D-Bus connection: Connection refused
.
Уведомление о снятии поддержки: этот ответ устарел начиная с systemd 248 (выпуск март 2021 г.). Пожалуйста, используйте systemctl -M
, как объяснил Эрик Шёлюнд в своем ответе.
У меня была такая же проблема, когда я подключился к своему gentoo ящику удаленно через ssh. В моем случае это произошло потому, что переменные окружения XDG_RUNTIME_DIR
и DBUS_SESSION_BUS_ADDRESS
отсутствовали. Выполните следующие команды и попробуйте снова:
export XDG_RUNTIME_DIR="/run/user/$UID"
export DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/bus"
Если это помогает, вы можете поместить эти команды в ваш .bashrc. Думаю, должно быть более элегантное решение, чем .bashrc, но это зависит от вашей дистрибуции.
Редактировать:
войдя как root, я смог успешно запустить systemctl --user
как другой пользователь, используя su
следующим образом:
su -c 'XDG_RUNTIME_DIR="/run/user/$UID" DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/bus" systemctl --user status' username
или используя sudo
(заметьте, мне пришлось явно добавить соответствующий UID пользователя (1000) в путь ‘/run/user/’, но если вы запускаете это из bash скрипта, вы можете использовать $SUDO_UID вместо этого):
sudo -u username XDG_RUNTIME_DIR="/run/user/1000" DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/bus" systemctl --user status
systemd 248 (выпущен в марте 2021 г.) ввел поддержку синтаксиса -M username@
для указания другого пользователя.
Предполагая, что другой пользователь называется testuser, а услуга – foobar.service, вы можете теперь выполнить
sudo systemctl -M testuser@ --user restart foobar.service
Предполагая, что someuser
использует bash как свою оболочку входа, добавьте следующие exports в ~someuser/.bashrc
:
export XDG_RUNTIME_DIR="/run/user/$UID"
export DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/bus"
Затем, пользователь с root/sudo правами может взаимодействовать с systemd someuser
, обернув команду runuser
:
sudo runuser -l someuser -c "systemctl --user restart some-template@$some-service.service"
У меня была такая же ошибка (Failed to connect to bus: No such file or directory
) при выполнении следующей команды на Ubuntu 20.04:
systemctl --user mask tracker-store.service tracker-miner-fs.service tracker-miner-rss.service tracker-extract.service tracker-miner-apps.service tracker-writeback.service
Проблема была из-за алиаса:
alias systemctl="sudo systemctl"
Он заменял systemctl
на sudo systemctl
, и sudo вызывал ошибку.
Переменные окружения:
export XDG_RUNTIME_DIR="/run/user/$UID"
export DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/bus"
не использовались из-за sudo
.
mkaito
написал в комментарии выше:
Думаю, sudo нужно их в белом списке, потому что он по умолчанию очищает окружение.
.
Ответ или решение
Управление пользовательскими юнитами systemd другого пользователя
Перенимая роль IT-эксперта, давайте детально рассмотрим, как один пользователь, или root, может управлять пользовательскими сервисами systemd другого пользователя.
Проблема: Ошибка соединения с D-Bus
Часто при попытке выполнить команду systemctl --user
от имени другого пользователя возникает ошибка: Failed to get D-Bus connection: Connection refused. Это связано с тем, что при переключении контекста через sudo
или su
, соединения с D-Bus теряются из-за отсутствия соответствующих переменных среды.
Предварительные шаги: Настройка переменных окружения
Для корректного управления юнитами systemd в контексте другого пользователя, необходимо выставить важные переменные окружения:
export XDG_RUNTIME_DIR="/run/user/$UID"
export DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/bus"
Эти переменные определяют директорию для сеансовых данных и адресацию D-Bus. Включите эту настройку в файл .bashrc
соответствующего пользователя для автоматического применения при каждом сеансе.
Решение: Использование runuser и sudo
При использовании su
или sudo
, важно правильно установить контекст и передать требуемые переменные:
Для su
:
su -c 'XDG_RUNTIME_DIR="/run/user/$UID" DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/bus" systemctl --user restart имя_сервиса' имя_пользователя
Для sudo
:
sudo -u имя_пользователя XDG_RUNTIME_DIR="/run/user/1000" DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/bus" systemctl --user restart имя_сервиса
В скриптах удобно использовать переменную $SUDO_UID
для динамического определения UID пользователя.
Решение начиная с systemd 248: Новая функция -M username@
С выходом новой версии systemd (248), требуется использовать обновленный синтаксис для управления сервисами:
sudo systemctl -M имя_пользователя@ --user restart имя_сервиса
Эта команда позволяет корректно управлять сервисами другого пользователя без необходимости ручного вмешательства в переменные окружения.
Заключение
Теперь у вас есть несколько способов контролировать системные службы systemd другого пользователя. Каждый из них подходит для различных сценариев использования и степени контроля. Если вы регулярно сталкиваетесь с необходимостью таких операций, рекомендуется создать скрипт, который сократит время на настройки и упростит процесс. Убедитесь, что используете актуальные версии systemd, чтобы использовать все доступные обновления и улучшения.
Для наиболее оптимального SEO этот контент следует адаптировать под конкретные запросы и ключевые слова, связанные с управлением systemd и его настройками.