Скрипт, обрабатывающий события системы с помощю DBus

    Dbus — средство межпроцессного взаимодействия. Другими словами, средство позволяющее одной программе «отдавать приказы» другой программе.
    В сети легко найти примеры, как из командной строки с помощью DBus управлять различными программами. Но слабо раскрыта тема, как отслеживать сигналы исходящие от других программ. В данной статье хочу исправить эту несправедливость и разобрать пример обработки событий получаемых от системы посредством Dbus.

    Помимо привязок к языкам программирования для Dbus существует ряд консольных программ, позволяющих использовать его из командной строки.
    • qdbus — позволяет вывести на консоль список сервисов и их интерфейсы, а также отправить команды приложениям.
    • dbus-send — позволяет отправить команды приложениям.
    • dbus-monitor — выводит на консоль информацию о полученных сигналах в момент их получения.

    Также при работе с DBus представляет интерес программа qdbusviewer — графическое приложение, позволяющее изучить имеющиеся в системе программы с поддержкой DBus.

    И так, обещанный пример.


    Задача: написать скрипт, который при установлении соединения с интернетом запустит клиент яндексдиска.
    Запускаем qdbusviewer и ищем, какой сервис может сообщить об изменении состояния сети. На вкладке System bus видим сервис org.freedesktop.NetworkManager. Если в данном сервисе пройти по пути /org/freedesktop/NetworkManager, обнаружим объект реализующий интерфейс org.freedesktop.NetworkManager. В данном интерфейсе есть сигнал StateChanged. Проверяем: Жмём на сигнале правой кнопкой мыши и выбираем Connect. Отключаем, подключаем сетевой интерфейс, видим приходящие сигналы, сообщающие статус сети. То, что нам надо.
    Теперь добьёмся такого же результата в командной строке. Будем использовать команду dbus-monitor. Вводим в командной строке:
    dbus-monitor --system "sender=org.freedesktop.NetworkManager, path=/org/freedesktop/NetworkManager, member=StateChanged"
    

    Здесь опция --system ­— указание слушать системную шину. В кавычках указан фильтр интересующего нас сигнала. Сервис org.freedesktop.NetworkManager, путь /org/freedesktop/NetworkManager и сигнал StateChanged.
    Отключаем, подключаем сетевой интерфейс. В процессе изменения состояния сети на консоль выводятся всё новый строки:
    signal sender=org.freedesktop.DBus -> dest=:1.540 serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired
       string ":1.540"
    signal sender=:1.2 -> dest=(null destination) serial=1870 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=StateChanged
       uint32 20
    signal sender=:1.2 -> dest=(null destination) serial=1883 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=StateChanged
       uint32 40
    signal sender=:1.2 -> dest=(null destination) serial=1899 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=StateChanged
       uint32 70
    

    На каждый полученный сигнал выводится по 2 строки. Первая с описанием сигнала, Вторая со значением аргумента. К слову, если у сигнала будет больше аргументов, то и строк будет больше.
    Экспериментально определено, статусу соединённой сети соответствует значение 70.
    Строго говоря, значения констант надо смотреть в документации NM_STATE (спасибо avalak за ссылку)

    Теперь нам надо обрабатывать получаемые сигналы и формировать команду запуска яндексдиска. Вводим в командной строке:
    dbus-monitor --system "sender=org.freedesktop.NetworkManager, path=/org/freedesktop/NetworkManager, member=StateChanged" | sed -u -n 's/   uint32 70/yandex-disk start/p'
    

    Мы дополнили предыдущую команду строкой | sed -u -n 's/ uint32 70/yandex-disk start/p'. Здесь обрабатываем каждую поступившую от dbus-monitor строку с помощью программы sed. Опция -u говорит sed-у выводить результат сразу же, не откладывая в буфер. Опция -n — не выводить ни чего, пока не будет явной команды. В одинарных кавычках указана команда программе sed: заменить в строке фразу " uint32 70" фразой «yandex-disk start» и вывести результат. Такая команда преобразует текст
    signal sender=org.freedesktop.DBus -> dest=:1.540 serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired
       string ":1.540"
    signal sender=:1.2 -> dest=(null destination) serial=1870 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=StateChanged
       uint32 20
    signal sender=:1.2 -> dest=(null destination) serial=1883 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=StateChanged
       uint32 40
    signal sender=:1.2 -> dest=(null destination) serial=1899 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=StateChanged
       uint32 70
    signal sender=:1.2 -> dest=(null destination) serial=1870 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=StateChanged
       uint32 20
    signal sender=:1.2 -> dest=(null destination) serial=1883 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=StateChanged
       uint32 40
    signal sender=:1.2 -> dest=(null destination) serial=1899 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=StateChanged
       uint32 70
    

    в
    yandex-disk start
    yandex-disk start
    

    Т. е. при каждом соединении с сетью формируется команда yandex-disk start.

    Наконец окончательный вариант:
    dbus-monitor --system "sender=org.freedesktop.NetworkManager, path=/org/freedesktop/NetworkManager, member=StateChanged" | sed -u -n 's/   uint32 70/yandex-disk start/p' | sh
    

    Отправляет сформированные команды запуска яндесдиска на исполнение.

    Сохраняем в файл
    #!/bin/bash
    dbus-monitor --system "sender=org.freedesktop.NetworkManager, path=/org/freedesktop/NetworkManager, member=StateChanged" | sed -u -n 's/   uint32 70/yandex-disk start/p' | sh
    

    Делаем файл исполняемым. И добавляем в автозапуск. Теперь при соединении с интернетом будет автоматически стартовать клиент яндексдиска.

    Аналогично можно обрабатывать сигналы любых приложений поддерживающих DBus.

    В статье была рассмотрена возможность автоматизировать обработку сигналов поступающих от различных приложений с помощью DBus. Для отслеживания сигналов в консоли применяется программа dbus-monitor. Данная программа позволяет отлавливать как все сигналы всех сервисов, так и отфильтровать только то, что нас интересует.
    Несколько примеров:
    • dbus-monitor — все согналы ото всехприложений.
    • dbus-monitor --system «sender=org.freedesktop.NetworkManager» — все сигналы от NetworkManager.
    • dbus-monitor --system «sender=org.freedesktop.NetworkManager, path=/org/freedesktop/NetworkManager» — все сигналы от объекта /org/freedesktop/NetworkManager в сервисе NetworkManager.
    • dbus-monitor --system «sender=org.freedesktop.NetworkManager, path=/org/freedesktop/NetworkManager, member=StateChanged» — только сигнал StateChanged от объекта /org/freedesktop/NetworkManager в сервисе NetworkManager

    dbus-monitor на каждый полученный сигнал выводит несколько строк. В первой описание сигнала, в последующих значения аргументов.
    Далее обрабатываем получаемые сигналы, как нам заблагорассудится.
    Share post

    Similar posts

    Comments 10

      +9
      Если нужно что-то сложнее чем отправка команды через dbus-send/qdbus лучше сразу использовать python. Сильно упрощает жизнь.
      Для исследования dbus есть d-feet.

      > Экспериментально определено, статусу соединённой сети соответствует значение 70.
      Для стандартных интерфейсов почти всегда есть спецификации.
      NM_STATE
        0
        Спасибо за ссылку. Стоит указать её в статье.
        0
        Оффтоп
        Кто-нибудь может подсказать Как выпилить поддержку иксов из dbus в ubuntu?, чтобы можно было работать с dbus на сервере?
          0
          В телефоне Nokia N900 большинство событий отражались в Dbus и можно было много интересных вещей делать: я с его помощью заставлял телефон кротко вибрировать, когда на другом конце брали трубку (простенький shell-скрипт). Почти все события можно было через dbus отловить.
            0
            Причастный оборот в заголовке не обособлен. «Итак» пишется слитно. Да, я знаю, что надо в личку. Специально пишу в комментариях.

            Если человеку лень вогнать статью в чекер орфографии или самому вычитать… ну не знаю. Такое я пишу в комментариях.
              0
              А «и так» пишется раздельно :) Не каждый чекер в состоянии определить, где должно быть «итак», а где «и так».
            –4
            >Задача: написать скрипт который при установлении соединения с интернетом запустит клиент яндексдиска.
            Нет запятых между частами сложноподчинённого предложения; «яндексдиска».

            >В данной стать хочу исправить эту несправедливость и разобрать пример обработки событий получаемых от системы по средствам Dbus.
            Пропущена «я», не обособлен причастный оборот; опять кривые слова: «стать», «по средствам»…
            ru.wiktionary.org/wiki/посредством

            >dbus-send — позволяет отправить команды приложениям.
            Тире не нужно.

            >В статье была рассмотрена возможность автоматизировать обработку сигналов поступающих от различных приложений с помощью DBus.
            Причастный оборот, опять.

            >Теперь при при соедиением с интернетом будет автоматически стартовать клиент яндексдиска.
            Очевидно же, что человек просто поленился вычитать статью: «при при».

            Я даже не вычитывал, просто глазами проглядел.
              0
              Грубо конечно, но спасибо за желание помочь. Поправил статью.
                –2
                Заголовок забыли исправить.

                >dbus-monitor — все согналы ото всехприложений.

                >Опция -n — не выводить ни чего, пока не будет явной команды.

                Серьёзно? Поправили статью?

            Only users with full accounts can post comments. Log in, please.