Отправка уведомления notify-send другому пользователю на той же системе

Вопрос или проблема

Можно ли использовать 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 вещи, чтобы это заработало:

  1. Установить переменную окружения DBUS_SESSION_BUS_ADDRESS в то же значение, что и у пользователя, которому я хотел отправить уведомление – в моем случае это было unix:path=/run/user/1000/bus. Вы можете сделать это следующим образом:
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
  1. Добавить разрешения для пользователя на доступ к пути, указанному в DBUS_SESSION_BUS_ADDRESS – в моем случае не хватало только разрешений на выполнение в /run/user/1000. Следующее было достаточно:
setfacl -m u:user_name:x /run/user/1000/

Помните, что каталог /run воссоздается при каждом перезагрузке, поэтому вам, вероятно, нужно будет выполнять это из какого-либо сценария при загрузке. Вы должны сделать это от имени пользователя, который может устанавливать разрешения на каталог – либо root, либо владелец этого каталога.

  1. Изменить политику 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 в многопользовательской среде

  1. Отправка уведомлений конкретному пользователю:
    Для отправки уведомлений конкретному пользователю, вам потребуется знать его имя и убедиться, что у него запущена X-сессия. Один из возможных подходов — использование команды sudo с передачей сообщения от имени другого пользователя, что требует соответствующих прав:

    sudo -u username DISPLAY=:0 notify-send "Сообщение" "Содержание сообщения"

    Обратите внимание, что username должен иметь текущую X-сессию.

  2. Настройка переменной окружения DBUS_SESSION_BUS_ADDRESS:
    Чтобы успешно отправить уведомление, часто требуется указать корректный адрес D-Bus для сессии пользователя. Адрес можно найти в /run/user/UID/bus, где UID — это идентификатор целевого пользователя.

    export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus

    Права доступа к этому пути могут требовать настройки командой setfacl для предоставления необходимых разрешений исполнителю уведомления.

  3. Изменение политики D-Bus:
    Возможно, понадобится скорректировать политику D-Bus, чтобы разрешить указанным пользователям отправку уведомлений. Это делается путем добавления конфигурационного файла /etc/dbus-1/session-local.conf:

    <busconfig>
       <policy context="mandatory">
           <allow user="user_name"/>
       </policy>
    </busconfig>

    Эта конфигурация исполняется один раз от имени суперпользователя (root).

  4. Отправка уведомлений всем пользователям:
    Для широковещательной рассылки уведомлений всем пользователям на системе используется команда wall для текстовых терминалов. Однако для графических окружений удобнее организовывать сканирование всех D-Bus-сессий и отправку уведомлений на каждую из них.

    Скрипт на основе рассмотренного примера, который сканирует /proc и отправляет уведомления в каждую сессию, может быть полезен для автоматизации этой задачи.

Рекомендуемые шаги для внедрения

  • Настроить права доступа: Убедитесь, что система корректно настраивает доступ к D-Bus, DBUS_SESSION_BUS_ADDRESS и X-сессиям при включении.
  • Автоматизация через systemd: Интегрируйте исполнение скриптов и настройки в системные службы посредством systemd, включив условия на запуск после графического окружения (After=graphical.target).
  • Безопасность: Осуществляйте эффективное управление правами и доступом, чтобы избежать утечек информации между пользователями.

Заключение

Технология нотификаций на многопользовательских системах может существенно улучшить взаимодействие и реактивность рабочих процессов. Подходы к реализации уведомлений на основе notify-send являются гибкими, позволяя адаптировать решения под конкретные нужды и ограничения системы. However, следуя описанным шагам и рекомендациям, вы можете эффективно настроить отправку сообщений через notify-send, адаптируя процесс под уникальные условия вашего рабочего окружения.

Оцените материал
Добавить комментарий

Капча загружается...