Вопрос или проблема
Можно ли использовать notify-send для отправки сообщений другим пользователям в системе?
Предпочтительно указанному пользователю, но можно и по всей системе.
Я использую Ubuntu/Debian с установленной библиотекой libnotify.
Если у вас есть пароль другого пользователя, вы можете выполнить sudo -u somedude notify-send Hello
. У somedude должна быть запущена X-сессия.
Редактировать:
Нашел этот сценарий для использования с cron:
#!/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin
export DISPLAY=:0.0
export $(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep -session)/environ )
TIME=$1
shift
/usr/bin/notify-send -t 36000 $1 $2
Если пользователи находятся в терминалах, полезными будут следующие команды –
write user [tty]
или чтобы отправить всем пользователям
wall
Я наткнулся на следующий проект, реализующий уведомление пользователей: tinynotify-send
Мне понадобился аналогичный инструмент для отправки уведомлений во все сессии. Вот мое решение: https://unix.stackexchange.com/a/230062/93227
Он сканирует /proc, чтобы найти все шины сессий, и затем выполняет notify-send на каждой из них (один раз на шину). Все аргументы передаются без изменений настоящему notify-send.
#!/bin/bash
/bin/grep -sozZe '^DBUS_SESSION_BUS_ADDRESS=[a-zA-Z0-9:=,/-]*$' /proc/*/environ \
| /usr/bin/php -r '
$busses = array();
array_shift($argv);
while($ln = fgets(STDIN)) {
list($f, $env) = explode("\0", $ln, 2);
if (file_exists($f)) {
$user = fileowner($f);
$busses[$user][trim($env)] = true;
}
}
foreach ($busses as $user => $user_busses) {
foreach ($user_busses as $env => $true) {
if (pcntl_fork()) {
posix_seteuid($user);
$env_array = array("DBUS_SESSION_BUS_ADDRESS" => preg_replace("/^DBUS_SESSION_BUS_ADDRESS=/", "", $env));
pcntl_exec("/usr/bin/notify-send", $argv, $env_array);
}
}
}
' -- "$@"
Я использовал это в сценарии, запускаемом из службы systemd, выполненной от имени root на Arch Linux:
user_to_notify="me"
id_of_user_to_notify=$(id -u "$user_to_notify")
sudo -u "$user_to_notify" DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/"$id_of_user_to_notify"/bus notify-send "Message title" "Message content"
Без установки переменной DBUS_SESSION_BUS_ADDRESS
я получал ошибку:
Error spawning command line “dbus-launch –autolaunch=268ff42abb2141a0ae8a8e13bc6210da –binary-syntax –close-stderr”: Child process exited with code 1
В моем случае (Xubuntu 18.04) мне нужно было сделать 3 вещи, чтобы это заработало:
- Установить переменную окружения
DBUS_SESSION_BUS_ADDRESS
в то же значение, что и у пользователя, которому я хотел отправить уведомление – в моем случае это былоunix:path=/run/user/1000/bus
. Вы можете сделать это следующим образом:
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
- Добавить разрешения для пользователя на доступ к пути, указанному в
DBUS_SESSION_BUS_ADDRESS
– в моем случае не хватало только разрешений на выполнение в/run/user/1000
. Следующее было достаточно:
setfacl -m u:user_name:x /run/user/1000/
Помните, что каталог /run воссоздается при каждом перезагрузке, поэтому вам, вероятно, нужно будет выполнять это из какого-либо сценария при загрузке. Вы должны сделать это от имени пользователя, который может устанавливать разрешения на каталог – либо root, либо владелец этого каталога.
- Изменить политику dbus, чтобы позволить этому пользователю доступ к шине сессии. Этот ответ объясняет, как это сделать. Вкратце, создайте файл
/etc/dbus-1/session-local.conf
со следующим содержанием:
<busconfig>
<policy context="mandatory">
<allow user="user_name"/>
</policy>
</busconfig>
Замените user_name
на имя пользователя, который должен иметь возможность отправлять уведомления.
После того, как вы выполните шаги 2 и 3, вы можете отправить уведомление с помощью:
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus notify-send "Test message"
В моем случае мне нужно было делать уведомления из моей службы, запущенной systemd, и следующее было достаточным (шаг 3 нужно выполнить один раз от имени root):
[Unit]
After=graphical.target
[Service]
ExecStartPre=/usr/bin/setfacl -m u:serviceuser:x /run/user/1000
ExecStart=/srv/myapp/bin/myapp
User=serviceuser
PermissionsStartOnly=true
Environment="DISPLAY=:0.0"
Environment="DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus"
[Install]
WantedBy=graphical.target
Ответ или решение
Использование notify-send
для отправки сообщений пользователям на той же системе — это задача, с которой сталкиваются многие системные администраторы и IT-специалисты при работе в многопользовательских окружениях на Ubuntu или Debian. Библиотека libnotify
играет ключевую роль в реализации уведомлений через команду notify-send
. Давайте подробно разберемся, как это можно реализовать.
Возможности использования notify-send в многопользовательской среде
-
Отправка уведомлений конкретному пользователю:
Для отправки уведомлений конкретному пользователю, вам потребуется знать его имя и убедиться, что у него запущена X-сессия. Один из возможных подходов — использование командыsudo
с передачей сообщения от имени другого пользователя, что требует соответствующих прав:sudo -u username DISPLAY=:0 notify-send "Сообщение" "Содержание сообщения"
Обратите внимание, что
username
должен иметь текущую X-сессию. -
Настройка переменной окружения DBUS_SESSION_BUS_ADDRESS:
Чтобы успешно отправить уведомление, часто требуется указать корректный адрес D-Bus для сессии пользователя. Адрес можно найти в/run/user/UID/bus
, где UID — это идентификатор целевого пользователя.export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
Права доступа к этому пути могут требовать настройки командой
setfacl
для предоставления необходимых разрешений исполнителю уведомления. -
Изменение политики D-Bus:
Возможно, понадобится скорректировать политику D-Bus, чтобы разрешить указанным пользователям отправку уведомлений. Это делается путем добавления конфигурационного файла/etc/dbus-1/session-local.conf
:<busconfig> <policy context="mandatory"> <allow user="user_name"/> </policy> </busconfig>
Эта конфигурация исполняется один раз от имени суперпользователя (root).
-
Отправка уведомлений всем пользователям:
Для широковещательной рассылки уведомлений всем пользователям на системе используется командаwall
для текстовых терминалов. Однако для графических окружений удобнее организовывать сканирование всех D-Bus-сессий и отправку уведомлений на каждую из них.Скрипт на основе рассмотренного примера, который сканирует
/proc
и отправляет уведомления в каждую сессию, может быть полезен для автоматизации этой задачи.
Рекомендуемые шаги для внедрения
- Настроить права доступа: Убедитесь, что система корректно настраивает доступ к D-Bus, DBUS_SESSION_BUS_ADDRESS и X-сессиям при включении.
- Автоматизация через systemd: Интегрируйте исполнение скриптов и настройки в системные службы посредством
systemd
, включив условия на запуск после графического окружения (After=graphical.target
). - Безопасность: Осуществляйте эффективное управление правами и доступом, чтобы избежать утечек информации между пользователями.
Заключение
Технология нотификаций на многопользовательских системах может существенно улучшить взаимодействие и реактивность рабочих процессов. Подходы к реализации уведомлений на основе notify-send
являются гибкими, позволяя адаптировать решения под конкретные нужды и ограничения системы. However, следуя описанным шагам и рекомендациям, вы можете эффективно настроить отправку сообщений через notify-send
, адаптируя процесс под уникальные условия вашего рабочего окружения.